Область оценки Perl

#perl #scope #eval

Вопрос:

Согласно perldoc, оценка строки должна выполняться в текущей области. Но следующий простой тест, по-видимому, противоречит этому.

Нам нужны следующие два простых файла для настройки теста. Пожалуйста, положите их в одну папку.

test_eval_scope.pm

 package test_eval_scope;  use strict; use warnings;  my %h = (a=gt;'b');  sub f1 {  eval 'print %h, "n"';   # print %h, "n"; # this would work  # my $dummy = %h; # adding this would also work }  1  

test_eval_scope.pl

 #!/usr/bin/perl  use File::Basename; use lib dirname (__FILE__); use test_eval_scope;  test_eval_scope::f1();  

Когда я запускаю программу, я получаю следующую ошибку

 $ test_eval_scope.pl Variable "%h" is not available at (eval 1) line 1.  

Мой вопрос в том, почему переменная %h выходит за рамки.

Я внес некоторые изменения и обнаружил следующее:

  1. Если я запущу без eval(), как в приведенном выше комментарии, это сработает. это означает, что %h должен быть в области видимости.
  2. Если я просто добавлю, казалось бы, бесполезное упоминание в коде, как в приведенном выше комментарии, eval() тоже будет работать.
  3. Если я объединю файл pl и pm в один файл, eval() тоже будет работать.
  4. Если я объявлю %h с «нашим» вместо «моего», eval() тоже будет работать.

Я столкнулся с этим вопросом, когда писал большую программу, которая анализировала пользовательский код во время выполнения. Мне не нужны решения, так как у меня есть множество обходных путей выше. Но я не могу объяснить, почему приведенный выше код не работает. Это влияет на мою гордость за perl.

Моя версия perl-v5.26.1 в Linux.

Спасибо вам за вашу помощь!

Ответ №1:

Подлодки фиксируют только переменные, которые они используют. Поскольку f1 он не используется %h , он не захватывает его и %h становится недоступным f1 после того, как он выходит за рамки, когда модуль завершает выполнение.

Любая ссылка на var, в том числе оптимизированная, приводит к тому, что подменю захватывает переменную. Таким образом, работает следующее:

 sub f1 {  %h if 0;  eval 'print %h, "n"'; }  

ДЕМОНСТРАЦИЯ:

 $ perl -M5.010 -we'  {  my $x = "x";  sub f { eval q{$x} }  sub g { $x if 0; eval q{$x} }  }   say "f: ", f();  say "g: ", g(); ' Variable "$x" is not available at (eval 1) line 1. Use of uninitialized value in say at -e line 8. f: g: x  

Комментарии:

1. оптимизация, по-видимому, является ключевым фактором.

2. Это не просто оптимизация; она позволяет своевременно уничтожать переменные.