我曾经认为unless
和if 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
]
上面的代码片段显示unless
和if not
会导致子程序看到最后评估的表达式的不同值。
这似乎是因为if not
认为not
是EXPR
的一部分,而unless
并不认为它是{{1}的一部分}}
问题
是否有其他代码使用示例,其中两者不完全同义?
答案 0 :(得分:3)
不同之处在于,对于unless
案例,最后评估的表达式为$value % 3
,而对于if not
案例,最后评估的表达式为not $value % 3
< / p>
not
表现为一个简单的运算符,而if
和unless
是while
和for
之类的语言结构,它们不参与表达式
在任何情况下,依赖子例程的返回值是不好的做法,除非它对每个路径都有return
,或者它以表达式结束。 perldoc perlsub
说这个
如果未找到
return
且最后一个语句是表达式,则返回其值。如果最后一个语句是循环控制结构,如foreach
或while
,则返回的值未指定。
所以只是因为你认为你知道没有return
的子程序也会评估什么,除非你用表达式结束你的子程序,否则它实际上并不可靠,并且可能会在以后改变Perl的版本。
只需为你的病情写一个return
,你的代码就会立即变得更加清晰。或者你可以使用条件表达式,它指定为两个条件
cond_exp => sub {
my ( $value ) = @_;
$value % 3 ? "" : "$value is a multiple of 3";
}