为什么"我的@变量"在子内部并由子/子修改表现得如此奇怪

时间:2016-12-08 04:58:51

标签: perl scope subroutine

我有一个奇怪的行为(对Python程序员)子程序,简化如下:

use strict;
use Data::Dumper;
sub a {
  my @x;
  sub b { push @x, 1; print "inside: ", Dumper(\@x); }
  &b;
  print "outside: ", Dumper(\@x);
}
&a;
&a;

我发现结果是:

inside: $VAR1=[ 1 ]
outside: $VAR1 = [ 1 ]
inside: $VAR1=[1, 1]
outside: $VAR1= []

在调用&a时我的想法是,@x在" my @x"之后是空数组并且在" &b"之后有一个元素,然后死了。每次拨打&a时,都是一样的。所以输出应该都是$VAR1 = [ 1 ]

然后我读了一些类似命名的子例程,在符号表中定义了一次,然后我做了#34; my $b = sub { ... }; &$b;",这似乎对我有意义。

如何解释?

1 个答案:

答案 0 :(得分:12)

根据“perlref”手册页:

  

命名子例程是在编译时创建的,所以它们是词法   变量[即,他们的'my'变量]被分配给父变量   来自第一次执行父块的词法。如果是父母   范围是第二次输入,其词法再次创建,而   嵌套的潜艇仍然引用旧的。

换句话说,一个已命名的子例程(您的b)将其@x绑定到父子例程的“第一个”@x,因此当调用a时第一次,b1添加到@x,内部和外部副本都引用同一版本。但是,第二次a被调用时,会创建一个新的@x词法,但b仍然指向旧的词法,因此它会向该列表添加第二个1并打印它(内部),但是当a打印其版本时,它会打印出(空)全新的词法(外部)。

匿名子程序不会出现此问题,因此当您编写my $b = sub { ... }时,内部@x始终引用a的词汇@x的“当前”版本}。