Perl 在什么情况下才是「;除非;不同于;如果不是的话;?

Perl 在什么情况下才是「;除非;不同于;如果不是的话;?,perl,Perl,我曾经认为除非和如果不是完全等效的,但这让我意识到它们可以在列表上下文下产生不同的输出: use strict; use warnings; use Data::Printer; use feature 'say'; my %subs = ( unless => sub { my ( $value ) = @_ ; return "$value i

我曾经认为
除非
如果不
是完全等效的,但这让我意识到它们可以在列表上下文下产生不同的输出:

use strict;
use warnings;
use Data::Printer;
use feature 'say';

my %subs = (
              unless => sub {
                            my ( $value ) = @_ ;

                            return "$value is a multiple of 3"
                              unless $value % 3 ;
                        },
              if_not => sub {
                            my ( $value ) = @_ ;

                            return "$value is a multiple of 3"
                              if not $value % 3 ;
                        },
           );

for my $name ( keys %subs ) {

    my $sub = $subs{$name};
    say $name;
    my @results = map { $sub->($_) } 1 .. 10;
    p @results;
}
输出

if_not
[
    [0] "",
    [1] "",
    [2] "3 is a multiple of 3",
    [3] "",
    [4] "",
    [5] "6 is a multiple of 3",
    [6] "",
    [7] "",
    [8] "9 is a multiple of 3",
    [9] ""
]
unless
[
    [0] 1,
    [1] 2,
    [2] "3 is a multiple of 3",
    [3] 1,
    [4] 2,
    [5] "6 is a multiple of 3",
    [6] 1,
    [7] 2,
    [8] "9 is a multiple of 3",
    [9] 1
]
上面的代码片段显示,
除非
如果不
会导致子例程看到上一个计算表达式的不同值

这似乎是因为<代码>如果不是认为<代码>不是/代码>是代码> ExpR<代码>的一部分,而<代码>除非不认为它是<代码> EXPR的一部分。

问题


有没有其他代码用法的例子表明这两种用法不是完全同义的?

区别在于,对于
除非
的情况,最后计算的表达式是
$value%3
,而对于
如果不是
的情况,最后计算的表达式是
不是$value%3

not
表现为一个简单的运算符,而
if
except
是类似
while
for
的语言构造,它们不涉及表达式的值

在任何情况下,依赖子例程的返回值都是不好的做法,除非每个路径都有
返回值
,或者它以表达式结尾。这么说

如果未找到
return
,并且如果最后一条语句是表达式,则返回其值。如果最后一条语句是循环控制结构,如
foreach
while
,则返回值未指定

因此,仅仅因为您认为您知道不带
返回的子例程也会计算什么,它实际上并不可靠,除非您用表达式结束子例程,并且在以后的Perl版本中可能会发生更改

只要为你的另一种情况写一个
返回值
,你的代码就会立即变得更清晰。或者,您可以使用一个条件表达式来指定两个条件都要返回的值

cond_exp => sub {
    my ( $value ) = @_;

    $value % 3 ? "" : "$value is a multiple of 3";
}

“<代码>如果不是认为<代码>不是/代码>是代码> ExpR<代码>的一部分,而<代码>除非不认为它是<代码> EXPR的一部分。code>not
是一个操作符,而
if
除非
是流控制语言单词。在您的
案例中,除非
案例中根本没有
,因此“将
视为表达式的一部分”不适用。如果您也尝试了
除非不…
,那么您会发现
not
始终是表达式的一部分,就像
一样
if
除非
只是根据表达式的真实性以相反的方式进行操作。如果“$value%3”为false,则可以找到“return”表达式。如果“$value%3”为真,则无法找到“return”表达式,“If_NOT”将返回“NOT$value%3”和“除非”将返回“$value%3”。我认为“问题”之前的最后一句话可能有误导。这里的要点是
返回if EXPR
似乎将
if
(自身)作为最后处理的对象(因此首先计算
EXPR
,然后计算
if
的结果),而
返回除非EXPR似乎最后处理了
EXPR
。(这不是关于
不是
。也不是关于
返回
-ing。)如果
如果EXPR
除非EXPR
导致不同的求值顺序,我认为这很重要。@zdim:If
都不返回值,因此无法“求值”。在没有明确的
return
语句的情况下返回的值是
EXPR
,它是
$value%3
不是$value%3
。我不明白你为什么说“这不是关于<代码>不是<代码>。也不是关于<代码>返回<代码>-ing。”当它非常清楚的时候。在这两种情况下,计算
EXPR
,然后执行
返回
,具体取决于
EXPR
@Borodin Agree的值——我认为答案中的前两段是明确的。然而,我不同意“需要结束”这一问题。我认为这是一个好问题。基本结构行为的感知差异将是显著的,应该尽一切努力加以提高。实际上,它是如何表述的并不重要——对于类似的东西,可以要求“其他示例”。
除非
如果
之间在操作上解释的“无差异”也很重要,因为
除非
通常被视为
如果不
。我想问题已经清楚了,但我并不是要解释为什么这两个人的行为有所不同;我想知道是否还有其他例子表明
除非
如果不
的行为不同。我们已经习惯于看到
,除非
可以重写为
,如果不是
,那么上面例子中的差异一开始就有点令人惊讶。有没有其他例子表明使用
的结果会导致不同的结果?@Zaid:直接回答你的问题几乎是不可能的。任何其他这样的情况都会像这一个一样模糊,仅仅因为我不能立即想象任何其他情况并不意味着没有。您的问题来自一种误解,即
除非
如果不
的等价性并不意味着您可以在不改变代码语义的情况下用一个字符串替换另一个字符串。我希望,如果我解释了差异的来源,你自己就能发现并避免类似的情况。@Zaid:人们说
excel
等于
if not
的意思是
excel