可能的方法:
使用push:
my @list;
push @list, 'foo' if $foo;
push @list, 'bar' if $bar;
my @list = (
$foo ? 'foo' : (),
$bar ? 'bar' : (),
);
使用x!!
Boolean list squash operator:
my @list = (
('foo') x!! $foo,
('bar') x!! $bar,
);
哪一个更好,为什么?
答案 0 :(得分:12)
嗯,他们都做了不同的事情。
然而,所有其他因素相同,
push @list, 'foo' if $foo;
是最直接传达其含义的陈述,因此应该首选。
如果你不得不停下来思考那些应该像推送数组元素一样简单的语句,你就会做错事。
my @list = (
$foo ? 'foo' : (),
$bar ? 'bar' : (),
);
如果这是其他地方正在进行的一些巨大初始化的一部分,那么就可以了。
我认为使用
my @list = (
('foo') x!! $foo,
('bar') x!! $bar,
);
表示程序员已经 - 我该怎么把它? - issues。
顺便说一下,没有一种称为x!!
复合运算符的东西。 !!
为double logical negation。它将一个任意的false值转换为一个已定义但值为false的值(空字符串),当0
期望一个数字时,它会产生perl
。真值将转换为1
。在这里,!!
在$foo
和$bar
上运行,并且x!! $foo
编写它会不必要地模糊代码的含义。
x
是repetition operator。所以,
('foo') x !!$foo;
表示重复('foo')
一次或根本不重复,具体取决于$foo
是真还是假,。
PS:当然,事实证明有一个PerlMonks article引入了所谓的布尔列表压缩算子。我看了article并发现它难以令人信服。
答案 1 :(得分:5)
我想建议我将“可读”的方法配音:
sub maybe ($$) { $_[1] ? $_[0] : () }
my @list = (
maybe("foo", $foo),
maybe("bar", $bar),
);
它具有这个所谓的x!!
运营商的许多好处(虽然稍微长一些),但还有一个额外的好处,就是你可以在以后再回来时理解你的代码。
sub maybe {
my($var, $cond, @rest) = @_;
return @rest unless $cond;
return $var, @rest;
}
my @list = (
maybe "foo", $foo,
maybe "bar", $bar,
);
无论我们如何处理原型,Perl都会尝试将其解析为maybe("foo", $foo, maybe("bar", $bar))
,因此如果我们想要抛弃括号,我们只需要做出正确的结果。
答案 2 :(得分:2)
虽然OP没有要求它,但这个问题为use Benchmark;
提供了一个很好的借口
以下是代码:
use strict;
use warnings;
use Benchmark qw( cmpthese);
my $foo = 1;
my $bar = "true";
cmpthese( -10, {
"push" => sub {
my @list;
push @list, 'foo' if $foo;
push @list, 'bar' if $bar;
},
"?::" => sub {
my @list = (
$foo ? 'foo' : (),
$bar ? 'bar' : ()
);
},
"x!!" => sub {
my @list = (
('foo') x!! $foo,
('bar') x!! $bar
);
}
});
这是一些典型的结果:
Rate x!! ?:: push
x!! 646539/s -- -8% -12%
?:: 701429/s 8% -- -5%
push 736035/s 14% 5% --
鉴于brian d foy 7% estimate对Benchmark
的不确定性,push
似乎是最快的成长方式。
总结:
$need4speed ? do { push @like $this} : try { something('less' x!! $obfuscated) };
# DISCLAIMER: This is not valid code
答案 3 :(得分:1)
我个人在这种情况下使用$foo ? 'foo' : ()
,因为很明显(与('foo') x!! $foo
相比),不需要特别努力(与('foo') x !!$foo
比较)并且可以在列表上下文中使用(与push @list, 'foo' if $foo;
比较)。
但是,当然,答案取决于您选择最佳选项的标准。如果你通过混淆比较它们,('foo') x!! $foo
肯定会赢。如果你通过笨拙来比较它们,push @list, 'foo' if $foo;
将是第一个。或许你的意思是表现?我猜不是: - )
但如果你用好的风格比较它们,我的选择是$foo ? 'foo' : ()
。