Почему это "!!- считается дурным тоном в Перле?


во время недавнего процесса собеседования я представил некоторый пример кода Perl, который использовал так называемый "секрет" !!оператор. Позже, при обсуждении кода, один из интервьюеров спросил меня, почему я решил использовать это, и указал, что это считается плохим тоном. Он не уточнил, почему.

моя команда и я использовали этот оператор в течение многих лет, никогда не понимая, что это считалось "плохим тоном."

работает ли оператор " bang bang есть побочные эффекты или другое неожиданное поведение? Почему это, или может быть, считается "плохим тоном" некоторыми? Есть ли идиоматическая альтернатива?

Ниже приведены несколько примеров, где я бы считал !! приемлемо и/или желательно.

  1. фактический код в упражнении кодирования, который является примером добавления логических значений:

    while (my $line = <$F>) {
        # snip
        exists $counts{lines} and $counts{lines} += !! chomp $line;
    }
    
  2. использование логического значения в качестве хэш-ключа (явно упрощенный пример):

    sub foo {
        my ($input) = @_;
        my %responses = ( '' => "False", 1 => "True" );
        return $responses{ !! $input };
    }
    
  3. используя логическое значение в побитовой операции, или даже pack():

    sub foo {
        my ( $a, $b, $c ) = @_;
        my $result = !!$a + (!! $b)<<1 + (!! $c)<<2;
        return $result;
    }
    
  4. вам нужно сделать типизацию для использования внешней библиотекой / процессом, например базой данных, которая считает только определенные значения истинными:

    my $sth = $dbh->prepare("INSERT INTO table (flag,value) VALUES (?,?)")
    $sth->execute("i_haz_cheeseburger", !! $cheeseburger_string)
    
5 58

5 ответов:

код !! использует две неясные вещи в Perl: конкретные значения, которые ! возвращает, и что одним из возможных значений является dualvar (скаляр, содержащий как строку, так и число). Используя !! для соединения этих поведений, по общему признанию, содержательно. Хотя его содержательность может быть огромным плюсом, она также может быть довольно большим минусом. Не используйте функции, которые приводят к проекту, требующему, чтобы " использование Perl было запрещено в этом проекте."

есть много альтернативы $count += !! (some_expression) подсчитывать вхождения истинных значений этого выражения. Один из них-троичный,$count += (some_expression) ? 1 : 0. Это тоже немного неясно. Есть хороший компактный способ сделать то, что вы хотите, что пост-если:

$x++ if some_expression;

это говорит ровно то, что вы делаете.

я бы назвал это "плохим тоном", потому что это просто не нужно. Вам не нужно логическое преобразование в Perl. И поэтому в лучшем случае это избыточно, а в худшем-запутывание.

хотя есть некоторые действительно хорошие трюки, которые вы можете использовать в Perl, одна из самых больших проблем с языком (по крайней мере, перцептивно) заключается в том, что он довольно склонен "писать один раз" код.

в конце концов-зачем вам нужно "дважды отрицать" скаляр, чтобы получить логическое значение, когда вы можете просто проверить скаляр?

my $state = !! 'some_string';
if ( $state ) { print "It was true\n" };

или:

if ( 'some_string' ) { print "It was true\n" };

и это правда-вы можете написать какой-то ужасно непонятный код Perl благодаря "секретным" операторам, переменным на основе пунктуации и т. д. И это будет прекрасно работать - например-я до сих пор считаю это шедевром:3-D стереограмма, самовоспроизводящийся источник

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

по поводу альтернатив;

while (my $line = <$F>) {
    # snip
    exists $counts{lines} and $counts{lines} += !! chomp $line;
}

это ... подсчет, как часто вы успешно chompЭд линии я думаю? Поэтому в основном он просто подсчитывает количество строк в вашем вводе.

для этого, я думаю использовать $.'. Если я не пропустил что-то глубокое о вашем коде?

весь вопрос несколько субъективен, поэтому я хотел бы дать мнение, которое отличается от других ответов, опубликованных до сих пор. Я бы не считал двойное отрицание плохим тоном вообще, но я бы попытался избежать его, если есть более читаемая альтернатива. Что касается ваших примеров:

  1. использовать что-то вроде $count++ if $condition.

  2. значения истины как хэш-ключи? Это просто зло. По крайней мере, это удивительно для тех, кто должен поддерживать свой код.

  3. использование !! оправдано.
  4. здесь я бы использовал тернарный оператор. Не совсем понятно, как execute ведет себя, когда передается dualvar.

другая ситуация, когда это совершенно нормально использовать !! при приведении определенных значений к логическому, например, в операторе return. Что-то вроде:

# Returns true or false.
sub has_item {
    my $self = shift;
    return !!$self->{blessed_ref};
}

большинство программистов должны знать !! идиома из статически типизированных языков, где он часто используется в качестве приведения к bool. Если это то, что вы хотите сделать, и нет никакой опасности нежелательных побочных эффектов, идите с двойным отрицанием.

возможно, это не так плохо для кода только вы видите.

тем не менее, ваш коллега-разработчик может однажды увидеть, как он исправляет ошибку в вашем коде, и натыкается на это. Есть два варианта

  1. он думает, что вы совершили ошибку и удаляет один !, аннулировав свой код
  2. он думает, что это просто программная гниль, и удаляет оба !! не задумываясь. После рефакторинга какого-то другого кода он внезапно зависает... тип несоответствие?

в любом случае, это будет тратить время будущих разработчиков, если они не знакомы с ним. Понятный код никогда не для себя (Ну, это может помочь), но для любых других, кто когда-либо увидит ваш код.

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

  1. при работе над командным проектом или любым другим кодом, над которым могут работать многие другие разработчики, не запутывайте (или не следуйте политике компании)
  2. идя из того, что сказал Санчис, это вызовет больше работы, и не ясно отображает намерения кода.
  3. это просто не нужно, и как обсуждалось выше-это звучит так есть по крайней мере один сценарий, где результат не будет работать - отсюда и ошибка.
  4. показ использования неясного кодирования в интервью, когда есть более простой и понятный способ сделать это, не выглядит благоприятно в интервью.
  5. интервью-это место, где вы хотите показать, что вы командный игрок, а не то, что вы собираетесь выбить странное дерьмо, которое никто больше не понимает (если это не будет ответом на нерешенный вопрос, конечно)

p.s. было бы неплохо спросить интервьюера, почему он считает это "плохим тоном". Удобный интервью последующий Совет, было бы отправить ему спасибо и спросить его, почему он считает это "плохим тоном"