19

从 Perl 5.10 开始,现在可以对上下文变量进行词法范围$_,无论是显式地作为my $_;还是在given / when构造中。

有没有人发现词汇的好用处$_?它是否使任何构造更简单/更安全/更快?

让情况变得更复杂的情况呢?词法是否在$_您的代码中引入了任何错误?(因为写入的控制结构$_将使用词法版本,如果它在范围内,如果它包含任何子例程调用(由于失去动态范围),这可能会改变代码的行为)

最后,我想构建一个列表,以阐明何时$_用作词法、全局或根本无关紧要。


注意:这些实验性perl5-5.24功能不再是 perl 的一部分

4

4 回答 4

8

IMO,从词汇中出来的一件好事$_是新的_原型符号。

这允许您指定一个子例程,以便它采用一个标量,或者如果没有提供它将抓取$_

所以不要写:

sub foo {
    my $arg = @_ ? shift : $_;

    # Do stuff with $_
}

我可以写:

sub foo(_) {
    my $arg = shift;

    # Do stuff with $_ or first arg.
}

变化不大,但是当我想要这种行为时,它就简单多了。样板删除是一件好事。

当然,这会产生改变几个内置函数(例如chr)原型的连锁反应,这可能会破坏一些代码。

总的来说,我欢迎 lexical $_。它给了我一个工具,我可以用它来限制意外的数据修改和函数之间的奇怪交互。如果我决定$_在函数体中使用,通过词法化它,我可以确保我调用的任何代码$_都不会在调用代码中被修改。

动态范围很有趣,但在大多数情况下,我想要词法范围。再加上周围的并发症$_。我听说过关于简单地做的不可取的可怕警告local $_;——最好for ( $foo ) { }改用它。当我通过任何方式进行本地化时, Lexicalized$_给了我 100 次中的 99 次我想要$_的东西。Lexical$_使极大的便利性和可读性功能更加健壮。

我的大部分工作都必须使用 perl 5.8,所以我没有$_在大型项目中使用 lexical 的乐趣。但是,感觉这将大大有助于使使用$_更安全,这是一件好事。

于 2010-08-04T16:49:12.900 回答
3

我曾经发现当我在玩这个模块时出现了一个问题(错误这个词太强了) 。Inline这个简单的脚本:

use strict qw(vars subs);
for ('function') {
    $_->();
}
sub function {
  require Inline;
  Inline->bind(C => <<'__CODE__');
void foo() 
{
}
__CODE__
}

失败并显示Modification of a read-only value attempted at /usr/lib/perl5/site_perl/5.10/Inline/C.pm line 380.错误消息。在模块的内部深处Inline是一个想要修改的子程序$_,导致上面的错误消息。

使用

for my $_ ('function') { ...

或以其他方式声明my $_是解决此问题的可行解决方法。

(该Inline模块已修补以解决此特定问题)。

于 2010-08-04T18:44:57.317 回答
1

[基本原理:一个简短的附加答案,为可能路过的 perl 新手提供了一个快速总结。当搜索“perl lexical topic”时,可以在这里结束。]

到现在(2015 年),我想大家都知道,词汇主题(my $_和一些相关特征)的引入会在一开始导致一些难以检测的意外行为,因此被标记实验性的,然后进入了弃用阶段


部分摘要 #RT119315: 一个建议是use feature 'lextopic'; 使用新的词汇主题变量: $^_。另一点是,“主题化运算符的隐含名称......而不是”在与明确的词法函数($_例如词法map或)结合时效果最好lmapgiven/when尚不清楚这些方法是否会以某种方式使挽救成为可能。在实验和折旧阶段的来世,也许某些东西最终可能会继续存在于 CPAN 的河流中。

于 2015-03-09T15:15:23.177 回答
0

在这里没有遇到任何问题,尽管在谈到 Perls 魔法时,我倾向于遵循某种“不问,不说”的政策。即,通常不期望例程依赖于他们的同行使用非词汇数据作为副作用,也不让他们。

我已经针对各种 5.8 和 5.10 版本的 perl 测试了代码,同时使用 5.6 描述 Camel 作为偶尔参考。没有遇到任何问题。我的大部分东西最初都是为 perl 5.8.8 完成的。

于 2010-08-04T07:11:21.487 回答