Perl 5.10+中词汇$ _的好,坏和丑

时间:2010-08-03 19:28:01

标签: perl global lexical perl5.10

从Perl 5.10开始,现在可以对上下文变量$_进行词汇范围,显式为my $_;given / when构造。

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

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

最后,我想构建一个列表,阐明何时使用$_作为词汇,作为全局,或者根本不重要。


NB:截至perl5-5.24这些实验性功能为no longer part of perl

4 个答案:

答案 0 :(得分:8)

IMO,词汇$_中出现的一个很棒的事情是新的_原型符号。

这允许你指定一个子程序,这样它就会占用一个标量,或者如果没有提供,它会抓取$_

所以不要写:

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

    # Do stuff with $_
}

我可以写:

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

    # Do stuff with $_ or first arg.
}

这不是一个很大的改变,但是当我想要这种行为时,它会变得更加简单。拆除锅板是一件好事。

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

总的来说,我欢迎词汇$_。它为我提供了一个工具,可以用来限制意外的数据混合和函数之间奇怪的交互。如果我决定在函数体中使用$_,通过词法化,我可以确定无论我调用什么代码,$_都不会在调用代码时被修改。

动态范围很有趣,但在大多数情况下我需要词法范围。除此之外还有$_周围的并发症。我听到了关于简单地做local $_;的不可取之处的可怕警告 - 最好使用for ( $foo ) { }代替。$_。当我通过任何方式本地化$_时,词汇化$_给了我想要的99次100。词法$_使得便利性和可读性更加强大。

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

答案 1 :(得分:3)

我曾经在使用issue模块时发现了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模块以修复此特定问题。)

答案 2 :(得分:1)

[基本原理:一个简短的补充答案,其中包含可能经过的perl新人快速摘要。在搜索&#34; perl词汇主题&#34;一个人可以在这里结束。]

到现在为止(2015年)我认为众所周知,词汇主题(my $_和一些相关特征)的引入导致一些人在一开始就难以发现意外行为,因此marked作为experimental,然后输入deprecation stage


  

#RT119315的部分摘要:    一个建议是use feature 'lextopic'; to make use of a new lexical topic variable: $^_之类的。    另一个观点是&#34; implicit name for the topicalizing operator ... other than $_&#34;当与明确的词汇函数(例如词汇maplmap)结合使用时,效果最佳。这些方法是否能以某种方式挽救given/when尚不清楚。在实验和折旧阶段的来世,也许最终可能存在于CPAN河流中。   

答案 3 :(得分:0)

这里没有任何问题,尽管在涉及到Perls魔术时,我倾向于遵循“不要问,不要说”的政策。即这些例程通常不会通常依赖于他们的同伴将非词汇数据作为副作用,也不会让他们这样做。

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