题
由于我经常使用$ _,所以我想更好地了解其用法。据我了解和使用,$ _是隐式值的全局变量。
由于$ _似乎已经设置,是否有理由在$ _ 以外可读性上使用命名循环变量?
在什么情况下,$ _是全局变量很重要?
所以,如果我使用 通用标签
甚至 通用标签
与具有相同的作用 通用标签
但是它的作用相同吗?我想那不完全是,但实际区别是什么?
更新:
在此示例中,似乎$ _的范围也正确。不再是全球性的了吗?我正在使用5.12.3。 通用标签
可以正确打印1234one1234two1234three1234four。
对于全局$ _,我期望1234 4 1234 4 1234 4 1234 4 ..或我缺少明显的东西吗?
那么$ _什么时候是全局的?
更新:
好吧,在仔细阅读了各种答案和perlsyn之后,我得出了一个结论:
除可读性外,最好避免使用$ _,因为必须知道$ _的隐式本地化,并考虑到否则可能会遇到意外的行为。
感谢您对此事的澄清。
解决方案
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。所有其他地方都要求您本地()自行,因此,当您不可避免地忘记这样做时,您将注入潜在的错误。: - )
其他提示
使用$_
(隐式或显式)作为循环变量的经典失败模式是
通用标签
其中,因为for
/ foreach
中的循环变量绑定到了实际的列表项,这意味着while (<F>)
用从文件中读取的行覆盖了@myarray
。
$ _与在第二个示例中使用通常的命名方式命名变量相同。$ _只是当前循环中当前项目的快捷方式默认变量名,以节省执行快速,简单循环时的键入时间。我倾向于使用命名变量而不是默认变量。这样可以更清楚地知道它是什么,如果我碰巧需要进行嵌套循环,则不会有冲突。
由于$ _是全局变量,所以如果尝试使用它在先前代码块中具有的值,则可能会得到意外的值。新的代码块可能是循环或其他操作的一部分,该循环或其他操作将其自己的值插入$ _,从而覆盖了您期望的值。
使用$ _的风险在于它是全局的(除非您使用local $_
对其进行本地化),因此,如果您在循环中调用的某些函数也使用$ _,则这两种用法可能会相互干扰。
由于我不清楚的原因,这只是偶尔使我难受,但是如果在软件包中使用$ _,我通常会将其本地化。
$_
没什么特别的,它是许多功能的默认参数。如果您用$_
明确地对my
进行词法作用域,则perl将使用$_
的本地版本,而不是全局版本。没什么奇怪的,就像其他任何命名变量一样。
通用标签
您应该对输出感到有点困惑,直到发现perl将在循环退出时保留循环变量的原始值为止(请参见 perlsyn )。
注意上面的 ex2 。在这里,第二个循环使用在第一个循环中声明的词法范围的$_
。微妙,但可以预期。同样,此值将在退出时保留,因此两个循环不会相互干扰。