在什么情况下"除非"不同于"如果不是"?

时间:2017-07-17 22:39:35

标签: perl

我曾经认为unlessif not完全等效,但this Q&A让我意识到他们可以在列表上下文中产生不同的输出:

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
]

上面的代码片段显示unlessif not会导致子程序看到最后评估的表达式的不同值。

这似乎是因为if not认为notEXPR的一部分,而unless并不认为它是{{1}的一部分}}

问题

是否有其他代码使用示例,其中两者不完全同义?

1 个答案:

答案 0 :(得分:3)

不同之处在于,对于unless案例,最后评估的表达式为$value % 3,而对于if not案例,最后评估的表达式为not $value % 3 < / p>

not表现为一个简单的运算符,而ifunlesswhilefor之类的语言结构,它们不参与表达式

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

  

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

所以只是因为你认为你知道没有return的子程序也会评估什么,除非你用表达式结束你的子程序,否则它实际上并不可靠,并且可能会在以后改变Perl的版本。

只需为你的病情写一个return,你的代码就会立即变得更加清晰。或者你可以使用条件表达式,它指定为两个条件

返回的值
cond_exp => sub {
    my ( $value ) = @_;

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