Что происходит, когда у вас есть условный оператор и постфиксный условный оператор в одной и той же инструкции Perl? - PullRequest
6 голосов
/ 14 сентября 2009

Кто-нибудь может объяснить, как работает эта строка?

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

если $y <0, возвращается -pip2, но что возвращается, когда $y >= 0 и $x != 0?

Эта строка из этой функции:

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

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

Ответы [ 4 ]

20 голосов
/ 14 сентября 2009

Постфикс «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;
    }
}
7 голосов
/ 14 сентября 2009

так же, как

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 );
  }
}
6 голосов
/ 15 сентября 2009

Это хороший пример трудно читаемого кода.

Давайте сравним несколько разных способов переписать пример кода и посмотрим, как мы делаем это для сохранения краткости и улучшения читабельности.

Эта трехзначная версия выигрывает для краткости, но ее все еще трудно прочитать:

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;  
}

Все еще кратко, но читаемость улучшена.

Но как насчет использования if и unless? Можем ли мы также использовать сжатый, читаемый код?

По своей природе прямой подход 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;  
}

Легко проследить через вышесказанное и посмотреть, каков будет результат. Так читаемость выигрывает, но страдает краткость.

Я считаю, что использование форм модификатора оператора unless и if обеспечивает чистый способ добавить логику короткого замыкания в кусок кода:

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;  
}

Вложено, если предложения / else могут быть трудны для понимания. Небольшая осторожность при структурировании кода решения может значительно улучшить удобочитаемость и, следовательно, удобство обслуживания при сохранении краткого выражения базовой логики.

Запах кода, который должен быть здесь исправлен, представлял собой барочную комбинацию условного оператора (?:) с формой модификатора оператора if. Переставив порядок тестов и тщательно выбрав способ представления условной логики, мы смогли сохранить краткость и уточнить код.

2 голосов
/ 23 апреля 2012

Слишком много строк, используемых для решения проблемы, затрудняет сопровождение кода (всегда обязательна прокрутка). Решение с вложенным if в 4 раза длиннее. Представьте себе работу с экраном в 4 раза меньше. Мой любимый синтаксис:

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

Преимущество использования оператора постфикса уменьшается, если вы поместите их в следующую строку. Этот порядок строк (предложенный @daotoad) позволяет поместить условие постфикса в более простую строку.

Исходный синтаксис также хорош, но я не хотел бы работать с кодом, содержащим предложенный вложенный if из предыдущих постов.

...