2014-10-31 53 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 

更新

如果我评论线capture和右括号,然后执行预期print线。

+0

我可以在没有错误的情况下运行代码。 – choroba 2014-10-31 14:09:48

+0

虽然当然可能,但在建议外部框架搞砸之前,我总是确保非常确定。尤其是那些已经存在了一段时间的人。虽然你的问题是好的,否则可能会对未来的读者有所帮助,但我会认为这是建议是负责downvotes。 – DeVadder 2014-10-31 14:20:33

+0

您显示的代码全部在子程序中,对吗? – ysth 2014-10-31 15:58:48

回答

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 2014-10-31 15:34:52

+1

此问题不会导致不可用的警告。 – ysth 2014-10-31 15:57:41

+1

@ysth,这就是为什么我把它称为相关的警告,而不是“你应该看到的警告”。 – cjm 2014-10-31 16:05:14

4

的说明,请参见perldiag

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

在编译过程中,内部命名子或EVAL试图捕捉外部词汇不是 当前可用。这可能由于以下两个原因之一而发生。首先,外部词汇可以在外部尚未创建的匿名子程序中声明。 (请记住,命名潜艇是在编译时创建的,而匿名的潜艇是在运行时创建 。)例如,

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

在f是创建的时候,就无法捕捉到的当前值$ a,因为尚未创建匿名子例程 。相反,由于匿名子程序已经被创造出来,是活的下面也不会发出警告:

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

第二种情况是由一个eval访问已超出范围的变量引起的,例如,

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

这里,在使用eval“$ A”被编译时,f()是不是当前正在执行的,所以它的$一不可用于捕获。

+0

非常有趣。这如何转化为我的例子?它确实是“俘获”了吗? – 2014-10-31 14:18:31

+0

@ialarmedalien我现在已经更新了OP,因为如果我评论'capture'行,问题就会消失。 – 2014-10-31 14:35:41