修改$ _时可能出错?

caj*_*ine 6 perl

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

@some = map { s/xxx/y/; $_ } @some;
Run Code Online (Sandbox Code Playgroud)

perlcritic解释它是危险的,因为例如:

@other = map { s/xxx/y/; $_ } @some;
Run Code Online (Sandbox Code Playgroud)

和成员@someGOT 修改.了解.我有BPB书,它通过示例显示了上面的内容

@pm_files_without_pl_files
         = grep { s/.pm\z/.pl/xms && !-e } @pm_files;
Run Code Online (Sandbox Code Playgroud)

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

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

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

问题是:

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

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

Leo*_*ans 11

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

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

s/xxx/y/ for @some;
Run Code Online (Sandbox Code Playgroud)

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

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


Ilm*_*nen 7

代码就像你的例子:

@some = map { s/xxx/y/; $_ } @some;
Run Code Online (Sandbox Code Playgroud)

应该避免,因为它是多余的和令人困惑的.它看起来像左边的分配应该做的事情,尽管它实际上是一个无操作.的确,只写:

map { s/xxx/y/; $_ } @some;
Run Code Online (Sandbox Code Playgroud)

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

map { s/xxx/y/ } @some;
Run Code Online (Sandbox Code Playgroud)

这个版本至少具有使(合理地)明确map忽略返回值的优点,并且声明的实际目的是@some在适当的位置进行修改.

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

s/xxx/y/ for @some;
Run Code Online (Sandbox Code Playgroud)