Perl 5.10 中词法 $_ 的好处、坏处和丑陋之处

发布于 2024-09-12 07:56:42 字数 603 浏览 3 评论 0原文

从 Perl 5.10 开始,现在可以按词法限定上下文变量 $_ 的范围,可以显式为 my $_; 或在 given / when构造。

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

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

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


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

Starting in Perl 5.10, it is now possible to lexically scope the context variable $_, either explicitly as my $_; or in a given / when construct.

Has anyone found good uses of the lexical $_? Does it make any constructs simpler / safer / faster?

What about situations that it makes more complicated? Has the lexical $_ introduced any bugs into your code? (since control structures that write to $_ will use the lexical version if it is in scope, this can change the behavior of the code if it contains any subroutine calls (due to loss of dynamic scope))

In the end, I'd like to construct a list that clarifies when to use $_ as a lexical, as a global, or when it doesn't matter at all.


NB: as of perl5-5.24 these experimental features are no longer part of perl.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦开始←不甜 2024-09-19 07:56:42

IMO,词汇 $_ 带来的一件伟大的事情是新的 _ 原型符号。

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

因此,

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

    # Do stuff with $_
}

我可以写:

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

    # Do stuff with $_ or first arg.
}

不是一个大的改变,但当我想要这种行为时,它会简单得多。移除样板是一件好事。

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

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

动态作用域很有趣,但大多数情况下我想要词法作用域。除此之外,$_ 也带来了一些复杂性。我听说过关于简单地执行 local $_; 的不可取性的可怕警告 - 最好使用 for ( $foo ) { } 代替。当我通过任何方式本地化 $_ 时,词汇化的 $_ 可以 100 次提供我想要的东西。词法 $_ 使极大的便利性和可读性功能更加强大。

我的大部分工作都必须使用 perl 5.8,因此我没有在大型项目中享受使用词法 $_ 的乐趣。不过,感觉这对提高 $_ 的使用安全性有很大帮助,这是一件好事。

IMO, one great thing to come out of lexical $_ is the new _ prototype symbol.

This allows you to specify a subroutine so that it will take one scalar or if none is provided it will grab $_.

So instead of writing:

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

    # Do stuff with $_
}

I can write:

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

    # Do stuff with $_ or first arg.
}

Not a big change, but it's just that much simpler when I want that behavior. Boilerplate removal is a good thing.

Of course, this has the knock on effect of changing the prototypes of several builtins (eg chr), which may break some code.

Overall, I welcome lexical $_. It gives me a tool I can use to limit accidental data munging and bizarre interactions between functions. If I decide to use $_ in the body of a function, by lexicalizing it, I can be sure that whatever code I call, $_ won't be modified in calling code.

Dynamic scope is interesting, but for the most part I want lexical scoping. Add to this the complications around $_. I've heard dire warnings about the inadvisability of simply doing local $_;--that it is best to use for ( $foo ) { } instead. Lexicalized $_ gives me what I want 99 times out of 100 when I have localized $_ by whatever means. Lexical $_ makes a great convenience and readability feature more robust.

The bulk of my work has had to work with perl 5.8, so I haven't had the joy of playing with lexical $_ in larger projects. However, it feels like this will go a long way to make the use of $_ safer, which is a good thing.

下壹個目標 2024-09-19 07:56:42

我曾经发现一个问题(bug太严重了一个词)是我在使用 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 attempts at /usr/lib/perl5/site_perl/5.10/Inline/C.pm line 380. 错误消息。在 Inline 模块的内部深处,有一个子例程想要修改 $_,从而导致上面的错误消息。

使用

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

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

(对 Inline 模块进行了修补以解决此特定问题)。

I once found an issue (bug would be way too strong of a word) that came up when I was playing around with the Inline module. This simple script:

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

fails with a Modification of a read-only value attempted at /usr/lib/perl5/site_perl/5.10/Inline/C.pm line 380. error message. Deep in the internals of the Inline module is a subroutine that wanted to modify $_, leading to the error message above.

Using

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

or otherwise declaring my $_ is a viable workaround to this issue.

(The Inline module was patched to fix this particular issue).

等待圉鍢 2024-09-19 07:56:42

[理由:一个简短的附加答案,为可能路过的 Perl 新手提供快速摘要。当搜索“perl 词法主题”时,可以在这里结束。]

到目前为止(2015 年),我认为词法主题的引入(my $_ 和一些相关功能)导致了众所周知一些一开始就难以检测到的意外行为,因此标记实验,然后进入 弃用阶段


部分摘要 # RT119315
一项建议是诸如 use feature 'lextopic'; 使用新的
词汇主题变量:
$^_

另一点是“主题化运算符的隐式名称...除了 $_" 与显式词法函数结合使用时效果最佳(例如词法 maplmap)。这些方法是否能够以某种方式挽救given/when尚不清楚。在实验和折旧阶段的来世,也许有些东西最终可能会在 CPAN 的河流中继续存在。

[ Rationale: A short additional answer with a quick summary for perl newcomers that may be passing by. When searching for "perl lexical topic" one can end up here.]

By now (2015) I suppose it is common knowledge that the introduction of lexical topic (my $_ and some related features) led to some difficult to detect at the outset unintended behaviors and so was marked as experimental and then entered into a deprecation stage.


Partial summary of #RT119315:
One suggestion was for something like use feature 'lextopic'; to make use of a new
lexical topic variable:
$^_
.
Another point made was that an "implicit name for the topicalizing operator ... other than $_" would work best when combined with explicitly lexical functions (e.g. lexical map or lmap). Whether these approaches would somehow make it possible to salvage given/when is not clear. In the afterlife of the experimental and depreciation phases perhaps something may end up living on in the river of CPAN.

屋顶上的小猫咪 2024-09-19 07:56:42

虽然我在涉及 Perls 魔法时倾向于遵循“不问,不说”的政策,但这里没有遇到任何问题。即,例程通常不会依赖于它们的同级使用非词汇数据作为副作用,也不会让它们这样做。

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

Haven't had any problems here, although I tend to follow somewhat of a "Don't ask, don't tell" policy when it comes to Perls magic. I.e. the routines are not usually expected to rely on their peers screwing with non lexical data as a side effect, nor letting them.

I've tested code against various 5.8 and 5.10 versions of perl, while using a 5.6 describing Camel for occasional reference. Haven't had any problems. Most of my stuff was originally done for perl 5.8.8.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文