Использование «если» по сравнению с «если» для условных выражений Perl

Каковы некоторые рекомендации по лучшему использованию if по сравнению с unless в коде Perl? Есть ли веские причины предпочесть тот или иной вариант в некоторых ситуациях?


person Community    schedule 15.06.2010    source источник


Ответы (9)


В Perl Best Practices рекомендуется никогда не использовать unless. Лично я считаю это бредом.

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

do_something() unless $should_not_do_that;

Я рекомендую избегать unless всякий раз, когда все становится сложнее, например, когда у вас будет elsif или else блоков. (К счастью или, возможно, к сожалению, в зависимости от вашей точки зрения, elsunless нет)

Кроме того, в любое время условное выражение представляет собой сложное выражение, состоящее из других логических значений. Например,

unless( $foo and !$bar )

Это чертовски запутанно и не имеет никаких преимуществ перед эквивалентным if.

person Community    schedule 15.06.2010
comment
Я не думаю, что unless нужно автоматически избегать для сложных выражений. if (!($foo and !$bar)) не обязательно чище, и программисту не нужно (и, возможно, не хотеться) применять теорему ДеМоргана, чтобы получить чище if (!$foo or $bar). - person Michael Carman; 16.06.2010
comment
@Michael Проблема с неприменением теоремы ДеМоргана заключается в том, что следующему программисту придется применять ее в своей голове, когда он читает код. Недавно я столкнулся с этим на работе с небольшим количеством кода, например unless ($obj->has_errors || !$obj->is_valid) { return 1 } # error handling code follows Или на английском языке. Если предыдущие действия над объектом не увенчались успехом, не запускайте код обработки ошибок. - person Ven'Tatsu; 16.06.2010
comment
Просто мои взгляды: пять лет и больше я ни разу не пожалел, что оставил Perl ради Python. unless — ключевое слово, которое я ни разу не использовал за три года работы с Perl; не потому, что я читал Best Practices, и не использовал это слово в обычном разговоре. Между прочим, лучшее, что я получил от Perl, — это регулярные выражения. Период. - person biocyberman; 20.02.2017

Если не считать одного эзотерического случая1, unless — это просто синтаксический сахар для if !. Он существует для того, чтобы вы могли писать более понятный и выразительный код. Его следует использовать, когда он достигает этой цели, и избегать, когда он мешает ей.

Я считаю, что unless наиболее полезен для управления потоком в циклах. например

while (<$fh>) {
    next unless /\S/;
    # ...
}

Для простых отрицаний я нахожу это более ясным, чем отрицание if — легко пропустить это ведущее ! при чтении кода.

unless ($condition) {
    do_something();
}

if (!$condition) {
    do_something();
}

Но не пишите unless ... else, потому что это просто раздражает.

В постфиксной форме он дает подсказку об ожидаемом пути по коду.

do_normal_thing() unless $some_unlikely_condition;


1) Последнее оцениваемое выражение отличается, что может повлиять на поведение подпрограмм без явного return.

person Community    schedule 15.06.2010
comment
Иногда я обнаруживаю, что отрицание читается более четко, если используется ключевое слово «не», а не «!», например: get_ready() if not $ready; - person Grant McLean; 16.06.2010
comment
Абсолютно отличный ответ. unless существует для улучшения читабельности. Помните об этом, и все остальное последует. - person daotoad; 17.06.2010
comment
Может ли кто-нибудь предоставить более подробную информацию о сноске (последнее оцениваемое выражение отличается, что может повлиять на поведение подпрограмм без явного возврата)? Я не могу найти документацию, связанную с этим. - person jfritz42; 23.10.2013
comment
@jfritz42: неявные возвращаемые значения задокументированы в perlsub. Нет документации о разнице между unless (EXPR) и if (!EXPR) в отношении неявных возвратов; это просто естественное следствие того, как они используются. Предполагая, что EXPR имеет значение true (поэтому блок условного выражения не введен) и что блока else нет, условие является последним вычисленным выражением, и, следовательно, его результатом является неявное возвращаемое значение. С unless это выражение равно EXPR (истинно), тогда как с if это !EXPR (ложно). - person Michael Carman; 23.10.2013
comment
Я не уверен, что согласен с этим! легко пропустить. Если это так, то должны ли мы заменить все операторы с одним символом на слова, например + на плюс, = на равно и т. д.? - person MikeKulls; 15.01.2014

Эмпирическое правило заключается в том, что «если» следует использовать нечасто.

Это особенно полезно в постфиксной форме, например:

delete_old_widgets() unless $old_widget_count == 0

Ситуации, в которых вы никогда не должны использовать, если:

  • с составным условием (и, или, не)
  • с предложением else
person Community    schedule 15.06.2010

Недавно я потратил час, пытаясь объяснить кому-то, как работают два вложенных предложения «если», их было трудно расшифровать без необходимости инвертировать их в операторы if с булевой логикой.

Если вы попытаетесь перевести его на английский язык, он поможет вам.

Простой, если работает нормально. Например.

«Если ты не будешь молчать, я буду игнорировать тебя».

unless ($quiet) {
    ignore();
}

Хотя я думаю, что это работает одинаково хорошо

«Если ты не будешь молчать, я буду тебя игнорировать»

if (not $quiet) {
    ignore();
}

когда это начинает усложняться, когда у вас есть отрицание.

«Если ты не будешь шуметь, я буду тебя игнорировать»

unless ( ! $noisy) {
    ignore();
}

Гораздо лучше написать как

«Если будешь шуметь, я тебя проигнорирую»

if ($noisy) {
    ignore();
}

Итак, не используйте «если», если у вас также есть отрицание.

Также не используйте «если еще»

unless ($quiet) {
    ignore();
}
else {
    give_a_sweet();
}

«Если ты не будешь молчать, я тебя проигнорирую, иначе я дам тебе конфетку»

Измените его, инвертировав условие.

if ($quiet) {
    give_a_sweet();
}
else {
    ignore();
}

«Если ты молчишь, я дам тебе конфету, иначе я тебя проигнорирую».

с более чем одним условием это становится грязным.

unless ($quiet and not $fidgit) {
    punish();
}

«Если ты не будешь молчать и не будешь ерзать, я тебя накажу».

(извините, мое понимание терпит неудачу здесь!)

опять отрицать.

if (not $quiet or $fidgit) {
    punish();
}

«Если ты не будешь молчать или будешь ерзать, я тебя накажу».

проблема с использованием «если» даже для самых простых случаев, они часто (самостоятельно или вне

Я надеюсь, что это ясно, когда вы должны или не должны использовать, если?

(если у вас нет другого мнения?)

person Community    schedule 18.03.2014

Хотя я понимаю мотивы подобных вопросов, я не верю, что действительно разумно сводить использование чего-то вроде unless к конкретным эмпирическим правилам. Это, как и многие вспомогательные синтаксические конструкции в Perl, предоставляется программистам в качестве незначительного удобства, помогающего им яснее формулировать свои мысли по своему усмотрению; Я видел столько же сказано ведущими разработчиками во многих смыслах в "Programming Perl". Нет высшей цели или рационализации. Я хорошо знаю, что это утончает вопрос, но единственное ограничение, которое я бы наложил на его использование, состоит в том, чтобы увидеть, что он служит своей более широкой цели - сделать код более ясным. Если получится, то все хорошо. Определение того, является ли код понятным, интуитивно понятно само по себе и не может быть сведено к большому количеству чрезмерно обобщенных условий использования, касающихся каждого нюанса встроенных модификаторов/операторов/общего синтаксиса, а также там, где ограничения и рекомендации необходимы в больших групповых проектах. Я не думаю, что имеет смысл так тонко делить волосы.

person Community    schedule 16.06.2010

Мое мнение никогда не использовать, если. Мои причины:

  • Я думаю, что синтаксис затрудняет чтение кода. Наличие единого метода выполнения if делает работу более простой и последовательной.
  • Если вам нужно добавить оператор else позже, вы действительно должны изменить его на if. Просто проще, если это уже если.
  • Если логика внутри оператора «если» становится более сложной, вы можете получить нечетный код, например «unless (x == 5 && y != 7). Это нечетно, потому что во второй проверке есть двойной отрицательный результат.
  • Есть и другие способы отрицания вещей, например, x != 5
  • Он более совместим с другими языками. Я не знаю ни одного другого языка, в котором есть оператор else, и я думаю, что для этого есть очень веская причина.

В perl действительно есть 4 способа написать оператор if, если, если и затем поставить галочку в конце строки, а не в начале. Я предпочитаю единый непротиворечивый метод, совместимый и с другими языками.

Только мои 0,02 доллара.

person Community    schedule 04.03.2013
comment
Итак, вы говорите, что do_use($feature) unless (!grep($_->name ne "perl" && $_->has_feature($feature), @languages)); доведя это до логического завершения, мы все будем писать на ассемблере или FORTRAN. :-) Я думаю, что даже если бы я никогда раньше не видел Perl, я мог бы правильно догадаться, что означает unless. - person Denis Howe; 05.03.2014
comment
Привет Денис, я действительно не верю аргументу, что логический вывод состоит в том, что мы в конечном итоге будем использовать ассемблер. Я пишу код на Perl, как если бы это был любой другой язык. Я даже больше не пишу или умираю. Я всегда буду писать if(!doSomething()) { die; }. Это делает код ОЧЕНЬ читаемым, чего не хватает большинству Perl-кода. Если вы занимаетесь техническим обслуживанием и придете после меня, вы получите много очень четкого кода, в котором нет никаких уловок и есть множество четко определенных функций. Вы читали код, который вы написали выше, он имеет тройное отрицание в имени eq perl, или это не так? Трудно сказать. - person MikeKulls; 07.03.2014
comment
@MikeKulls Не пишите код Perl, как если бы это был любой другой язык. Пишите идиоматический код на Perl, соответствующим образом используя специальные инструменты, которые Perl дает вам так, как ни один другой язык. - person Medlock Perlman; 02.03.2016

Кстати...

В Perl Best Practices рекомендуется никогда не использовать else. Лично я считаю это бредом.

После 20 с лишним лет предпочитая Perl любой из его альтернатив (большинство из которых не существовало бы, если бы Perl не предоставил шаблон), я не только согласен с вердиктом «безумие», я удивлен (обеспокоен), услышав, что «Best Practices ' хочет избавиться от него.

Тем не менее, я настоятельно предпочитаю код, написанный для ясности, в отличие от неявно запутанных альтернатив, которые некоторые программисты на Perl используют «просто потому, что они могут». «если» — это недвусмысленная противоположность «если» и, следовательно, очень полезная альтернатива внедрению отрицания в условное выражение «если», особенно если условное выражение содержит несколько операторов. И это обоснование применимо, даже если за ним следует else/elsif.

person Community    schedule 02.06.2018
comment
Помните, что в Perl Best Practises также говорится, что каждый шаблон регулярного выражения должен использовать модификаторы /msx. Дамиан, как правило, лучше, и я думаю, что он вполне мог изменить свое мнение о каком-то содержании. - person Borodin; 02.06.2018

Возможно, это просто личное мнение, но мне нравится использовать Unless, когда условие if начинается с !

person Community    schedule 11.08.2010

Синтаксис if(!$condition) эквивалентен If($condition), и то же самое, если вы поменяете НЕ на условие.

Лично я предпочитаю использовать только операторы IF. Почему? Потому что меньше запоминать. Если у вас есть 100 строк кода, половина из которых использует exclude(), а другая половина — if(), вам потребуется больше времени на отладку, чем если бы это были только операторы if().

Однако вы можете «наловчиться» с «если» и «если», так что переход между ними совсем не займет времени. Но дело не только в том, если() или если(). Не забывайте, что...

if($condition) {
    #passed-condition code
} else {
    #failed-condition code
}

...эквивалентно...

unless(!$condition) {
    #passed-condition code
} else {
    #failed-condition code
}

А как насчет if(){...}elsif(){...}? Как бы вы сделали эквивалент этого в exclude(){...}elsunless(){...}? Чем сложнее логика, тем сложнее становится переход между if() и exclude(). Чем меньше вам нужно запоминать и балансировать в памяти, тем быстрее вы будете отлаживать собственный код.

person Community    schedule 02.03.2016