修改$ _时可能出错?

时间:2015-08-10 16:37:41

标签: perl

以下代码可能有副作用吗?

@some = map { s/xxx/y/; $_ } @some;

perlcritic将其解释为危险,因为例如:

@other = map { s/xxx/y/; $_ } @some;

@some的成员修改了。了解。我有BPB书,它用例子

显示了上面的内容
@pm_files_without_pl_files
         = grep { s/.pm\z/.pl/xms && !-e } @pm_files;

我还阅读了章节" 列表处理副作用" /" 永远不要修改列表函数中的$ _ 。"及其粉丝。我也知道/r

要明确(尽管我可怕的英语很可能):

在第一个例子中,要点是修改原始@some

问题是关于:

  • 第一个例子 @some = map { s/xxx/y/; $_ } @some; 会导致一些不必要的副作用吗?如果是,何时?
  • 或者只是"没有推荐"方式(但无害否则)?

寻找一些答案,因为一些" perl初学者的书" - 因此仍然没有接受任何当前的答案。 ;)

3 个答案:

答案 0 :(得分:11)

perl的一个箴言一直是TIMTOWTDI:有不止一种方法可以做到这一点。如果两种方式具有相同的最终结果,则它们同样正确。这并不意味着没有理由偏向另一种方式。

在第一种情况下,(对我来说,YMMV)更明显地做

之类的事情
s/xxx/y/ for @some;

这主要是因为它的沟通意图更好。 for表明它是关于副作用的,而map表明它是关于返回值。虽然在功能上完全相同,但对于你的程序员来说这应该更容易理解(并且可能在6个月内为你自己理解)。

不止一种方式,但有些方法比其他方式更好。

答案 1 :(得分:7)

代码就像你的例子:

@some = map { s/xxx/y/; $_ } @some;

应该避免,因为它是多余的和令人困惑的。 看起来像左边的赋值应该做的事情,即使它实际上是一个无操作。的确,只写:

map { s/xxx/y/; $_ } @some;

会产生完全相同的效果,如下所示:

map { s/xxx/y/ } @some;

这个版本至少具有使(合理地)明确map的返回值被忽略的优点,并且该语句的实际目的是修改@some

但是,正如莱昂已经指出的那样,到目前为止,最清晰,最惯用的写作方式是:

s/xxx/y/ for @some;

答案 2 :(得分:3)

@some = map { s/xxx/y/; $_ } @some;

可以正常使用,但代码非常糟糕,因为你并没有明白你有效地做了

map { s/xxx/y/ } @some; @some = @some;

这已经表明你可以完成

map { s/xxx/y/ } @some;

但这是一个误导性和效率低下的

版本
s/xxx/y/ for @some;

这完全取决于可读性和可维护性。

请注意,您可以

use List::MoreUtils qw( apply );

@some = apply { s/xxx/y/ } @some;

在Perl 5.14 +中,

@some = map { s/xxx/y/r } @some;