有条件地在列表中包含元素的最佳方法是什么?

Eug*_*ash 7 perl list operators

可能的方法:

  1. 使用推送:

    my @list;  
    push @list, 'foo' if $foo;  
    push @list, 'bar' if $bar;  
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用条件运算符:

    my @list = (  
        $foo ? 'foo' : (),    
        $bar ? 'bar' : (),              
    );
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用x!!布尔列表squash运算符:

    my @list = (  
        ('foo') x!! $foo,  
        ('bar') x!! $bar,  
    );  
    
    Run Code Online (Sandbox Code Playgroud)

哪一个更好,为什么?

Sin*_*nür 12

嗯,他们都做不同的事情.

但是,所有其他因素都是平等的,

push @list, 'foo' if $foo;
Run Code Online (Sandbox Code Playgroud)

是最直接传达其含义的陈述,因此应该是首选.

如果你必须暂停并思考那些应该像推送数组元素一样简单的语句,那么你做错了什么.

my @list = (
    $foo ? 'foo' : (),
    $bar ? 'bar' : (),
);
Run Code Online (Sandbox Code Playgroud)

如果这是其他地方正在进行的一些巨大初始化的一部分,那就可以了.

我觉得用

my @list = (
    ('foo') x!! $foo,
    ('bar') x!! $bar,
); 
Run Code Online (Sandbox Code Playgroud)

表示程序员有 - 我怎么能把它?- 问题.

顺便说一下,没有这种称为x!!复合算子的东西.这!!双重逻辑否定.它将任意false值转换为已定义但为false的值(空字符串),该值0在使用perl期望数字时生成.真值转换为a 1.在这里,!!操作上$foo$bar和写它x!! $foo不必要的混淆了代码的含义.

x重复运算符.所以,

 ('foo') x !!$foo;
Run Code Online (Sandbox Code Playgroud)

意味着重复('foo')一次或根本不重复,取决于$foo分别是真还是假.

PS:当然,事实证明有一篇PerlMonks文章介绍了所谓的布尔列表压缩算子.我读了这篇文章,发现它没有说服力.

  • 同意,`x !!'对我来说有点太聪明了.我希望它不会成为一种成语. (2认同)

Chr*_*utz 5

我想建议我称之为"可读"的方法:

sub maybe ($$) { $_[1] ? $_[0] : () }

my @list = (
  maybe("foo", $foo),
  maybe("bar", $bar),
);
Run Code Online (Sandbox Code Playgroud)

它有这个涉嫌x!!操作员的许多好处(虽然稍微长一点),但还有额外的好处,你可以在以后再回来时理解你的代码.

编辑:原型没有帮助Perl解析任何更好,并没有让我们抛弃括号,它只是阻止Perl做我们不想要的事情.如果我们想抛弃这些问题,我们必须做一些工作.这是一个没有括号的替代版本:

sub maybe {
  my($var, $cond, @rest) = @_;
  return @rest unless $cond;
  return $var, @rest;
}

my @list = (
  maybe "foo", $foo,
  maybe "bar", $bar,
);
Run Code Online (Sandbox Code Playgroud)

无论我们如何处理原型,Perl都会尝试将其解析为maybe("foo", $foo, maybe("bar", $bar)),所以如果我们想要抛弃括号,我们只需要做出正确的结果.