试图理解困难的Perl语法:数组和空方括号

时间:2015-07-15 21:48:18

标签: arrays perl

我正在尝试分析一段包含以下内容的Perl代码:

unless( @{$avl->Rates() || []} ) {
  if(!$nobar) { push @rptmp, 'BAR' unless @rptmp; }
}

我认为我理解的内心动作。这意味着“如果$ nobar为false(在这种情况下为0),则将字符串'BAR'添加到数组@rptmp,除非@rptmp已存在。”

我遇到问题的部分是第一个“除非”条件:unless ( @{$avl->Rates() || []} )$avl->Rates()是一个返回列表的函数(或者是指向列表的指针?)。但对我来说真正令人困惑的部分是|| []。这是“或”某事,因此除非$avl->Rates()没有返回任何内容,否则不会选中它。但我不确定它是做什么的,特别是空方括号。如果它返回一些空的东西,它不会总是错误吗?还有,有更好的,或者至少更清晰的方式来写这个吗?

2 个答案:

答案 0 :(得分:5)

  

所以除非$avl->Rates()没有返回

,否则不会选中它

它不可能在标量上下文中返回任何内容。据推测,它返回对数组的引用或undef。 unless (@{ $avl->Rates })在后​​一种情况下会失败,因此编码器决定在这种情况下使用对空数组的引用。

[]

大致相当于

# Create an array, and return a reference to it.
do { my @anon; \@anon }

这有点浪费,但

if (!@{ $avl->Rates() || [] }) {
   ...
}

是常用的,因为它比

my $rates = $avl->Rates();
if (!$rates || !@$rates) {
   ...
}

以下内容更清晰,避免在不需要时调用Rates

if (!$nobar && !@rptmp) {
   my $rates = $avl->Rates;
   push @rptmp, 'BAR'
      if !$rates || !@$rates;
}

答案 1 :(得分:2)

嗯。让我们看看这个。我认为这是可怕的Perl,但其他人显然不同意。有很多人遇到unless问题(仅仅意为if not),在这种情况下,我表示同情:那里发生的事情太多了

这是整个事情

unless ( @{ $avl->Rates() || [] } ) {
  if ( !$nobar ) { push @rptmp, 'BAR' unless @rptmp; }
}

首先,我会像这样提取Rates的电话

my $rates = $avl->Rates();
unless ( @{ $rates || [] } ) {
  if ( !$nobar ) { push @rptmp, 'BAR' unless @rptmp; }
}

我不知道$avl可能是什么,但看起来它的Rates方法会返回数组引用或 false 值 - 可能undef。所以表达式$rates || []默认任何 false 来引用一个enpty数组。现在封闭的@{ ... }可以安全地取消引用它

测试是数组是否为空,我会写

unless ( $rates and @$rates )

即。 除非Rates方法返回 true 值并且它是对非空数组的引用

现在我们有另一个unless的内部声明,除了这次它写成if not,并且里面有一个真实的unless

if ( !$nobar ) {
    push @rptmp, 'BAR' unless @rptmp;
}

内部陈述很简单。除非数组为空,否则它会测试@rptmp true ,如果它为空,则将BAR推送到

附带的条件检查可能是一个选项$nobar,如果它是 true ,那么BAR永远不会被推到数组上,无论其他条件是什么

我会以这种方式重构整个方法,分别提取方法调用并在整个过程中使用unless

my $rates = $avl->Rates;

unless ( $rates and @$rates) {
    unless ( $nobar ) {
        push @rptmp, 'BAR' unless @rptmp;
    }
}

如果您是unless - 恐惧症,那么这里的版本仅使用if,但我觉得它不太可读

my $rates = $avl->Rates;

if ( not $rates or @$rates == 0 ) {
    if ( not $nobar ) {
        push @rptmp, 'BAR' if @rptmp == 0;
    }
}

我希望有帮助