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

ast*_*nic 6 syntax perl conditional-operator

任何人都能解释这条线是如何工作的吗?

return $y < 0 ? - pip2 : pip2 if $x == 0;
Run Code Online (Sandbox Code Playgroud)

如果$y <0它返回-pip2,但它返回时$y >= 0$x != 0

这一行来自这个功能:

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

    return $y < 0 ? - pip2 : pip2 if $x == 0;
    return atan( $y / $x );
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*xon 20

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

return $y < 0 ? - pip2 : pip2 if $x == 0;
Run Code Online (Sandbox Code Playgroud)

是相同的

if ($x == 0)
{
    return $y < 0 ? - pip2 : pip2 ;
}
Run Code Online (Sandbox Code Playgroud)

如果您对?:三元运算符感到困惑,那么可以将其重写为常规if语句,以实现此目的

if ($x == 0)
{
    if ($y<0)
    {
        return -pip2;
    }
    else
    {
        return pip2;
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ius 7

和它一样

if($x == 0){
  if($y<0){
    return -pip2;
  }else{
    return pip2;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后整个功能变为:

sub _atan {
  my( $y, $x ) = @_;
  if($x == 0){
    if($y<0){
      return -pip2;
    }else{
      return pip2;
    }
  }else{
    return atan( $y / $x );
  }
}
Run Code Online (Sandbox Code Playgroud)


dao*_*oad 6

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

让我们比较几种不同的方法来重写代码示例,看看我们如何保持简洁性和提高可读性.

这个三元版本仅为简洁而获胜,但仍难以阅读:

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

    return $x == 0 ? ($y < 0  ? -pip2 : pip2)
                   : atan( $y / $x );  
}
Run Code Online (Sandbox Code Playgroud)

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

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

    return $x != 0 ? atan( $y / $x ) : 
           $y < 0  ? -pip2           : pip2;  
}
Run Code Online (Sandbox Code Playgroud)

仍然简短,但可读性得到改善.

但是使用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;  
}
Run Code Online (Sandbox Code Playgroud)

通过上面的描述很容易,看看结果会是什么.因此可读性获胜,但简洁性受损.

我发现使用语句修饰符形式unlessif提供一种干净的方法来为一大块代码添加短路逻辑:

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

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

    return -pip2 if $y < 0;

    return pip2;  
}
Run Code Online (Sandbox Code Playgroud)

这是简洁和可读的,但对我来说,似乎我们得到的回报超过了我们的需要.

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

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

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

    return $y < 0  ? -pip2 : pip2;  
}
Run Code Online (Sandbox Code Playgroud)

此表单与上述任何表单一样简洁,但更容易理解:

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

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

    return $y < 0  ? -pip2 : pip2;  
}
Run Code Online (Sandbox Code Playgroud)

嵌套的if/else子句很难理解.在构造决策代码时要小心谨慎,这样可以极大地提高可读性,从而提高可维护性,同时保留底层逻辑的简洁表达.

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