perl-for循环不会修改`my`变量,但是修改`我们的’变量
在Perl 5.20中,for循环似乎能够修改模块范围的变量,但不能在父范围内修改一个词法变量(并且不会引入新的范围,如果
#!/usr/bin/env perl use strict; use warnings; our $x; sub print_func { print "$xn"; } for $x (1 .. 10) { print_func; } 打印1到10像你所期望的,但以下不: #!/usr/bin/env perl use strict; use warnings; my $x; sub print_func { print "$xn"; } for $x (1 .. 10) { print_func; } 发出以下警告10次: Use of uninitialized value $x in concatenation (.) or string at perl-scoping.pl line 8. 这里发生了什么?我知道Perl子程序不能嵌套(并且始终具有模块范围),因此它们似乎无法关闭我的变量.看来,在这种情况下,严格模式下的perl应该使用以下消息拒绝第二个程序: Global symbol "$x" requires explicit package name at perl-scoping.pl line 6. Global symbol "$x" requires explicit package name at perl-scoping.pl line 9. 即它应该拒绝子例程,因为自由变量没有被声明为任何地方,而for循环因为变量尚未被声明. 为什么Perl以这种方式行事? 解决方法
令人困惑的是,记录在案的行为可能源自于使循环迭代器变量成为隐含的??本地化全局而不是词汇的不良决定.从
Foreach Loops in perlsyn.
换句话说,循环迭代器总是被定位到循环中.如果它是全局的,那么它的行为就像在循环块中被声明为本地的.如果它是一个词汇,那么它的行为就像它在循环块中被声明的那样. 将这个应用于您的两个示例将有助于了解发生了什么. our $x; sub print_func { print "$xn"; } for $x (1 .. 10) { print_func; } 在该循环中有一个隐式的本地$x. 当其范围结束时恢复旧值.如果在for循环之后添加print $x,可以看到这一点. use v5.10; our $x = 42; for $x (1 .. 10) { say $x; } say $x; # 42 我们来看看你的代码涉及到词汇(我的变量). my $x; sub print_func { print "$xn"; } for $x (1 .. 10) { print_func; } 这里真正发生的是你有两个词汇变量,称为$x.一个是文件范围,一个是范围的循环. for循环中的内部$x先于外部$x.这被称为“阴影”. 在物理范围之外不能看到词汇. print_func()只看到外部未初始化的$x. 这里有一些风格的外卖. 始终将参数传递到您的函数中. 实际上,print_func应该有一个参数.那么你不用担心复杂的范围规则. sub print_func { my $arg = shift; print "$argn"; } for $x (1..10) { print_func($x); } 总是用于我的$x. 不要依赖于复杂的隐式for循环范围规则.总是用我的声明循环迭代器. for my $x (1..10) { print_func($x); } 避免全局变量 由于很难说出访问全球的内容,不要使用它们.如果你认为你需要一个全局的,写一个函数来控制对一个文件范围的词法的访问. my $Thing = 42; sub get_thing { return $Thing } sub set_thing { $Thing = shift; return } 声明您的变量接近他们使用的位置. Ye olde编码风格将做一些事情,例如将所有变量声明在文件或函数的顶部.这是一个非常非常非常古老的语言,它要求只在某些地方声明变量. Perl和大多数现代语言没有这样的限制. 如果您一次性声明您的变量,就很难知道它们的内容,很难知道使用或影响的变量.如果你声明它接近于它的第一次使用,限制什么可以影响它,并使它更明显它是什么. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |