Perl:为什么"last"不能用于退出grep或map?

vol*_*ron 18 perl

perldocs文档说以下有关last:

last不能用于退出返回一个值,例如一个块eval {},sub {}或者do {},并且不应当被用来退出一个grep()或地图()操作.

为什么grep()map()中避免它?我对地图特别好奇,因为它是foreach结构的替代品.文档似乎坚持在没有描述后果的情况下不做某事.

ike*_*ami 8

首先,意识到这一点grep并且map是透明的next,last并且redo就像if是一样.

$ perl -e'
   print "A";
   for (8,9) {
      print "B";
      print map { print "C"; next; print "D"; $_ } 1,2,3;
      print "E";
   }
   print "F\n";
'
ABCBCF
Run Code Online (Sandbox Code Playgroud)

但是文档并没有说last 不能用于退出map,它说不应该使用它.目前尚不清楚这意味着什么.

  • 不要使用他们认为他们会影响mapgrep
  • 不要那样使用它们,因为你的读者可能认为它们会影响mapgrep
  • 不要那样使用它们,因为它可以让Perl处于不稳定状态吗?
  • 不要那样使用它们,因为将来可能会改变行为?

我不知道.

我不认为这是#3,因为我不知道使用的任何不良副作用next,lastredo留下一个mapgrep回调.

有趣的是,离开mapgrep使用循环结构甚至不会发出警告,即使以相同的方式留下子.

$ perl -wE'while (1) { map { last; } 1; }'

$ perl -wE'while (1) { sub { last; }->(); }'
Exiting subroutine via last at -e line 1.
Run Code Online (Sandbox Code Playgroud)

  • 你必须对你的侵略和过度敏感进行研究.我所说的是我确信文件的意图.是的,这是你的替代品之一.我没有评论文件的含义是否明显.我根本没有反对你.请冷静下来. (4认同)
  • 我确信其意图是`last`(和`next`)不应该用于退出`map`或`grep`中的隐式循环,因为它实际上退出了*包含块*.特别要注意的是,虽然文件级别的`last`是非法的,但是'print"A"; 打印地图{print"B"; 持续; print"C";} 1,2,3; 打印"Z";`只打印`AB`,因此退出整个程序.底线是`map`提供从一个列表到另一个列表的*mapping*,**不是**,正如OP所说,是'foreach`的替代品. (2认同)

Bor*_*din 7

map用于一个列表映射到另一个列表.它当然不是替代品foreach.我经常看到像

map { print "$_\n" } @data;
Run Code Online (Sandbox Code Playgroud)

它犯了使用map它的副作用并抛弃结果列表的罪.你不会考虑使用

my $x = 99;
sqrt(my $y = $x * $x);
print $y;
Run Code Online (Sandbox Code Playgroud)

你会收到警告 出于同样的原因,你不应该map在你的意思使用for.

出于实际原因,请考虑一下

print "A";
print map { print "B"; last; print "C";} 1,2,3;
print "Z";
Run Code Online (Sandbox Code Playgroud)

OUTPUT

AB
Run Code Online (Sandbox Code Playgroud)

所以在这种情况下last退出整个程序.通常,使用lastnext在块mapgrep块内部退出包含块(如果有),否则退出整个程序.这是要避免的,因此" last......不应该用于退出grep()或map()操作".

  • @ikegami:我以为你比这更清楚.`map`构建并返回一个标量值列表,这些值在void上下文中被丢弃.我不明白你的观点*没有结果"字符串"扔掉*.是的,在void上下文中调用一个具有副作用的函数是有效的,但是我的例子使用`sqrt`,就像使用`map`一样,计算一个仅为了评估它的效果而被丢弃的值参数. (3认同)
  • @ikegami:我只能假设你是故意忽略了这一点并且为了它而拖钓.你的意见宽恕任何有效的Perl结构,所以你也允许在void上下文中使用`grep`和`sort`,因为内部行为符合上下文的行为?`for`修饰符也将列表放在最后,所以我看不到`map`甚至有这个优势.称我为骗子是粗鲁和分裂的:'perldoc -f map`中的第一句话也说同样的事,你也应该在那里提出问题.写下你将要做的事 - 在你讨厌的恶化中,我将不再进一步. (3认同)
  • 你的第二个论点同样存在缺陷.人们总是`func(我的$ y = EXPR)``chomp(我的$ x = <>);``utf8 :: decode(my $ decoding = $ encoded);`这两个都有返回值,这是不止一个人可以说在void上下文中的`map`! (2认同)
  • 混乱来自于首先将"map"想象成一个循环.这可能是它在内部实现的方式,但它是从一个列表到另一个列表执行*映射*.该块本质上是一个应用于源的每个成员以导出目标的相应成员的函数.函数(子例程)没有`last`语句. (2认同)