因为我使用$ _很多,我想更好地理解它的用法。就我所理解和使用而言,$ _是隐含值的全局变量。
由于$ _似乎已设置,是否有理由使用命名循环变量而不是可读性?
在什么情况下,重要的是_ _是一个全局变量?
所以,如果我使用
for (@array){
print $_;
}
甚至
print $_ for @array;
它与
具有相同的效果for my $var (@array){
print $var;
}
但它的功能是否相同?我想这不完全是但实际差异是什么?
更新:
在这个例子中,似乎$ _甚至是正确的范围。它不再是全球性的吗?我使用的是5.12.3。
#!/usr/bin/perl
use strict;
use warnings;
my @array = qw/one two three four/;
my @other_array = qw/1 2 3 4/;
for (@array){
for (@other_array){
print $_;
}
print $_;
}
正确打印1234one1234two1234three1234four。
对于全球$ _我预计1234 4 1234 4 1234 4 1234 4 ..或我错过了一些明显的东西吗?
什么时候是$ _ global呢?
更新:
好的,在仔细阅读了各种答案和perlsyn后,我得出了一个结论:
除了可读性之外,最好避免使用$ _,因为必须知道$ _的隐式本地化并考虑到否则可能会遇到意外行为。
感谢您澄清此事。
答案 0 :(得分:8)
使用$_
(隐式或显式)作为循环变量的经典失败模式是
for $_ (@myarray) {
/(\d+)/ or die;
foo($1);
}
sub foo {
open(F, "foo_$_[0]") or die;
while (<F>) {
...
}
}
其中,因为for
/ foreach
中的循环变量绑定到实际列表项,意味着while (<F>)
用文件中读取的行覆盖@myarray
。
答案 1 :(得分:8)
are there reasons to use named loop variables over $_ besides readability?
问题不在于它们是否被命名。问题是它们是“包变量”还是“词汇变量”。
请参阅Perl“应对范围”中使用的2个变量系统的非常好的描述:
http://perl.plover.com/FAQs/Namespaces.html
包变量是全局变量,因此应该避免出于所有常见原因(例如远距离行动)。
避免包变量是“正确操作”或“更难注入错误”的问题,而不是“可读性”的问题。
In what cases does it matter $_ is a global variable?
无处不在。
更好的问题是:
In what cases is $_ local()ized for me?
有些地方Perl会为你本地()ize $ _,主要是foreach,grep和map。所有其他地方都要求你自己本地()使用它,因此当你不可避免地忘记这样做时,你会注入一个潜在的错误。 : - )
答案 2 :(得分:3)
$ _与在第二个示例中使用通常使用的方式命名变量相同。 $ _只是当前循环中当前项的快捷默认变量名,以便在执行快速,简单的循环时节省输入。我倾向于使用命名变量而不是默认值。它使它更清楚它是什么,如果我碰巧需要做一个嵌套循环,没有冲突。
由于$ _是一个全局变量,如果您尝试使用它来自前一个代码块的值,则可能会得到意外的值。新的代码块可能是循环或其他操作的一部分,它将自己的值插入$ _,覆盖了您期望的那些。
答案 3 :(得分:2)
使用$ _的风险在于它是全局的(除非你使用local $_
进行本地化),因此如果你在循环中调用的某些函数也使用$ _,那么这两种用法都会产生干扰。
由于我不清楚的原因,这偶尔只会咬我,但如果我在包内使用它,我通常会本地化$ _。
答案 4 :(得分:1)
$_
除了它是许多函数的默认参数之外没有什么特别之处。如果您使用$_
明确地将my
范围用于词法范围,则perl将使用$_
的本地版本而不是全局版本。这没有什么奇怪的,它就像任何其他命名变量一样。
sub p { print "[$_]"; } # Prints the global $_
# Compare and contrast
for my $_ (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex1
for my $_ (b1..b5) { for (a1..a5) { p } } print "\n"; # ex2
for (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex3
for (b1..b5) { for (a1..a5) { p } } print "\n"; # ex4
你应该对输出略微神秘,直到你发现perl将在循环退出时保留循环变量的原始值(参见 perlsyn )。
注意上面的 ex2 。这里第二个循环使用在第一个循环中声明的词法范围$_
。微妙但预期。同样,这个值在退出时保留,因此两个循环不会干扰。