2014-10-31 6 views
-3

В следующем блоке кода я получаю эту ошибкуПочему переменная недоступна?

Variable "$host" is not available at /comp/xx.pm line 404. 

, где линия 404 является последней строки в блоке кода.

Вопрос

Я предполагаю, что это Capture модуль, Мессинг в if (defined $host) { ..., но как я могу обойти эту проблему?

use Capture::Tiny 'capture'; 

my $host = $::c{slaves}{$id} if (defined $id); 

my ($stdout, $stderr, $exit) = capture { 
    if (defined $host) { 
     print "---delete $snap on host\n"; 
    } else { 
     print "----delete $snap on master\n"; 
    } 
}; # line 404 

Update

Если я комментирую линия capture и ее закрывающую скобку, то он выполняет ожидаемую print линию.

+0

Я могу запустить код без ошибок. – choroba

+0

Хотя, конечно, возможно, я всегда буду уверен, что буду очень уверен, прежде чем предлагать внешние фреймворки испортить. Особенно те, что были вокруг какое-то время.В то время как ваш вопрос хорош в противном случае и может быть очень полезным для будущих читателей, я бы предположил, что это предложение, которое отвечает за downvotes. – DeVadder

+0

Код, который вы показываете, находится в подпрограмме, правильно? – ysth

ответ

6

Проблема эта линия:

my $host = $::c{slaves}{$id} if (defined $id); 

Использование my $x = value if condition в настоящее время не поддерживается в Perl. Это своего рода работы, но имеет странные угловые случаи. Это одно.

Сплит уступка от объявления переменной:

my $host; 
$host = $::c{slaves}{$id} if (defined $id); 

Вы можете прочитать некоторые детали в the documentation for the related warning.

+3

'my $ host = defined $ id? $ :: c {slaves} {$ id}: undef; 'также будет работать, если у вас есть сильная аллергия на выполнение этого на двух строках. – hobbs

+1

Эта проблема не приводит к отсутствию предупреждения. – ysth

+1

@ysth, поэтому я назвал это связанным предупреждением, а не «предупреждением, которое вы должны были видеть». – cjm

4

См perldiag для объяснения:

Variable "%s" is not available (W closure) 

Во время компиляции внутреннее имени подпрограммы или Eval пытается захватить внешний лексических, который не в настоящее время. Это может произойти по одной из двух причин. Во-первых, внешняя лексика может быть объявлена ​​во внешней анонимной подпрограмме , которая еще не создана. (Помните, что названные подлодки создаются во время компиляции, в то время как анонимные сабвуфер создается во время выполнения). Например,

  sub { my $a; sub f { $a } } 

В то время, создаются е, он не может захватить текущее значение $ a, так как анонимная подпрограмма еще не создана . С другой стороны, следующие не будет выдавать предупреждение, так как анонимная подпрограмма теперь была создана и живое:

  sub { my $a; eval 'sub f { $a }' }->(); 

Вторая ситуация вызвана Eval доступ к переменному, вышли за рамки, например, ,

  sub f { 
       my $a; 
       sub { eval '$a' } 
      } 
      f()->(); 

Здесь, когда «$ а» в Eval компилируется, е() в настоящее время не выполняется, так что его $ а не для захвата.

+0

Очень интересно. Как это переводится в мой пример? Действительно ли это «захват», который все испортил? –

+0

@ialarmedalien Я обновил OP, так как проблема исчезнет, ​​если я прокомментирую строку 'capture'. –

Смежные вопросы