当你在同一个 Perl 语句中有一个条件运算符和一个后缀条件时会发生啥?

Posted

技术标签:

【中文标题】当你在同一个 Perl 语句中有一个条件运算符和一个后缀条件时会发生啥?【英文标题】:What happens when you have a conditional operator and a postfix conditional in the same Perl statement?当你在同一个 Perl 语句中有一个条件运算符和一个后缀条件时会发生什么? 【发布时间】:2010-11-28 02:14:48 【问题描述】:

谁能解释一下这条线是如何工作的?

return $y < 0 ? - pip2 : pip2 if $x == 0;

如果$y &lt;0 它返回-pip2,但是当$y &gt;= 0$x != 0 时它返回什么?

这一行来自这个函数:

sub _atan 
    my( $y, $x ) = @_;

    return $y < 0 ? - pip2 : pip2 if $x == 0;
    return atan( $y / $x );

【问题讨论】:

【参考方案1】:

后缀“if”表示return语句只有在条件为真时才会执行,所以

return $y < 0 ? - pip2 : pip2 if $x == 0;

一样
if ($x == 0)

    return $y < 0 ? - pip2 : pip2 ;

如果您对 ?: 三元运算符感到困惑,也可以将其重写为常规 if 语句以产生这个

if ($x == 0)

    if ($y<0)
    
        return -pip2;
    
    else
    
        return pip2;
    

【讨论】:

我可能会用unless($x) ...写它 是条件运算符,不是三元运算符。 :) 我只是暗示它是 a 三元运算符,而不是 the 三元运算符 :) @Brad Gilbert 小心 unless($x)if ($x == 0) 有不同的含义。当$xundef00.0"""0" 时,unless($x) 将执行。 if ($x == 0) 将在 $x 为 00.0 以及任何未通过 look_like_number 或计算结果为 0 的字符串(例如 "0e0")时执行。【参考方案2】:

和这个一样

if($x == 0)
  if($y<0)
    return -pip2;
  else
    return pip2;
  

整个函数就变成了:

sub _atan 
  my( $y, $x ) = @_;
  if($x == 0)
    if($y<0)
      return -pip2;
    else
      return pip2;
    
  else
    return atan( $y / $x );
  

【讨论】:

【参考方案3】:

这是难以阅读的代码的一个很好的例子。

让我们比较几种重写代码示例的不同方法,看看我们在保持简洁性和提高可读性方面的表现。

这个只有三元的版本简洁,但仍然难以阅读:

sub _atan 
    my( $y, $x ) = @_;

    return $x == 0 ? ($y < 0  ? -pip2 : pip2)
                   : atan( $y / $x );  

我发现链式条件运算符 (?:) 只有在后续运算符位于 else 位置时才可读:

sub _atan 
    my( $y, $x ) = @_;

    return $x != 0 ? atan( $y / $x ) : 
           $y < 0  ? -pip2           : pip2;  

仍然很简短,但可读性有所提高。

但是使用ifunless 呢?我们也可以使用它们来编写简洁易读的代码吗?

就其性质而言,直接的 if/else 方法会更加冗长:

sub _atan 
    my( $y, $x ) = @_;

    my $atan;
    if( x == 0 ) 
        if( $y < 0 ) 
            $atan = -pip2;
        
        else 
            $atan = pip2;
        
    
    else 
        $atan = atan( $y / $x )
                

    return $atan;  

很容易追溯上面的内容,看看结果会是什么。所以可读性胜出,但简洁性会受到影响。

我发现使用 unlessif 的语句修饰符形式提供了一种将短路逻辑添加到代码块的简洁方法:

sub _atan 
    my( $y, $x ) = @_;

    return atan( $y / $x )
        unless $x == 0;

    return -pip2 if $y < 0;

    return pip2;  

这是简洁易读的,但在我看来,我们获得的回报比我们需要的要多。

因此,如果我们在混合中引入条件运算符,我们会得到

sub _atan 
    my( $y, $x ) = @_;

    return atan( $y / $x )
        unless $x == 0;       

    return $y < 0  ? -pip2 : pip2;  

这种形式与上述任何一种形式一样简洁,但更容易理解:

sub _atan 
    my( $y, $x ) = @_;

    return atan( $y / $x )
        unless $x == 0;

    return $y < 0  ? -pip2 : pip2;  

嵌套的 if/else 子句可能难以理解。在构建决策代码时稍加注意可以大大提高可读性和可维护性,同时保持底层逻辑的简洁表达。

这里要修复的代码异味是条件运算符 (?:) 与 if 的语句修饰符形式的巴洛克式组合。通过重新安排测试的顺序并仔细选择我们如何表示条件逻辑,我们能够保持简洁和清晰的代码。

【讨论】:

【参考方案4】:

用于解决问题的行数过多会使代码难以维护(总是不得不滚动)。嵌套 if 的解决方案要长 4 倍。想象一下使用小 4 倍的屏幕工作。我最喜欢的语法是:

sub _atan 
    my ($y, $x) = @_;
    return atan ($y / $x) if $x != 0;
    return $y < 0  ? -pip2 : pip2;

如果将后缀运算符放在下一行,则使用后缀运算符的好处会减少。 此行顺序(由@daotoad 建议)允许将后缀条件放在更简单的行上。

初始语法也不错,但我不想处理包含以前帖子中建议的嵌套 if 的代码。

【讨论】:

无论你把它放在哪里,后缀运算符的好处都是一样的。如果您的屏幕看不到 24 行代码,则说明您还有其他问题。 :)

以上是关于当你在同一个 Perl 语句中有一个条件运算符和一个后缀条件时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

当你在 MySQL 或 PostgreSQL 中有一个 TEXT 字段时,你应该把它放在一个单独的表中吗?

JavaScript 使用误区 5 (转)

JavaScript 使用误区

Perl基础---条件操作符

Coffeescript 中的条件运算符

Perl 语言语法学习