以下代码可能有副作用吗?
@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初学者的书" - 因此仍然没有接受任何当前的答案。 ;)
答案 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;