Вы предпочитаете if (var) или if (var! = 0)?

Я занимаюсь программированием на языках, производных от C, уже пару десятилетий. Где-то по ходу дела я решил, что больше не хочу писать:

if (var)    // in C
if ($var)   # in Perl

когда я имел в виду:

if (var != 0)
if (defined $var and $var ne '')

Я думаю, что отчасти это связано с тем, что у меня строго типизированный мозг, и в моем понимании «если» требует логического выражения.

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

Или, может быть, это просто потому, что сейчас я в основном программист на Java.

Каковы ваши предпочтения и почему?

Серьезно, я не понимаю, насколько это полезный вопрос? Догматическая проповедь в ответах меня так злит (в основном потому, что я не согласен)! Если у вас было 5 повторений и трудности с написанием английского, он был бы закрыт без дальнейших размышлений.

James Morris 30.04.2010 19:56

Мне просто было интересно узнать, что люди думают о подобных вопросах и думают ли они об этом вообще. Этому вопросу уже больше года. SO за это время сильно изменилась. И вы правы: сейчас много догматических проповедей о ТАК - кажется, не так уж много «живи и давай жить другим» - и я должен задаться вопросом, насколько репрезентативны такие идеи.

Adrian Pronk 01.05.2010 15:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
22
2
22 173
26
Перейти к ответу Данный вопрос помечен как решенный

Ответы 26

if (var)

Меньше печатать, если вы уверены, что не тестируете что-то не то.

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

PolyThinker 01.01.2009 15:46

if (v) на 3 нажатия клавиши меньше для ввода и чтения, так что это намного лучше.

Roberto Russo 01.01.2009 15:49

все дело в семантике. Спросите мою жену, она будет грустить, оба пути не читаются (она не программист). Для обученного программиста на C это совершенно ясно, поэтому я также предпочитаю короткий путь.

Ilya 01.01.2009 18:57

@PolyThinker, это неправда.

Zach Langley 04.01.2009 00:58

я предпочитаю

if (var != 0)

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

Я использую это, если только var не является логическим. Я никогда не делаю if (var == true).

Thomas Owens 01.01.2009 15:00

if (var) мне одинаково легко читать (если не проще). Чем больше читать, тем труднее понять. Но я согласен, что это чисто субъективно.

PolyThinker 01.01.2009 15:42

Я согласен с PolyThinker ... для меня if (var) легче читать, потому что читать меньше, и я уже понимаю его значение.

Jason Coco 02.01.2009 15:24

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

Steve Jessop 31.01.2009 05:44

Я предпочитаю явные тесты, если результат в круглых скобках не является явным логическим значением. Фраза «if (1)», хотя синтаксически и семантически верна с точки зрения языка, не логична. Оно должно быть истинным или ложным, а не приводиться автоматически.

Я предпочитаю читаемый логический код, чем меньше печатать каждый день.

Я также категорически презираю код вида:

if (gotError == FALSE) ...
if (isComplete == TRUE) ...

Если логическое значение правильно названо (а оно должно быть), правильный способ сделать это:

if (!gotError) ...
if (isComplete) ...

Это потому, что (используя reductio ad absurdum) boolVal == TRUE - это просто еще одно логическое значение, так где же остановиться?

if (isComplete == TRUE) ...
if ((isComplete == TRUE) == TRUE) ...
if (((isComplete == TRUE) == TRUE) == TRUE) ...
if ((((isComplete == TRUE) == TRUE) == TRUE) == TRUE)...

И так до бесконечности.

У меня есть несколько способов сделать это:

для логических значений:

if (x)

для ints:

if (x != 0)  // always compare, never assume true/false on int values

для указателей:

if (x /* != 0 */)  // I've always done this, not sure where I picked it up but I like it

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

Обновлено: обратите внимание, что 0 (вместо NULL) связано с тем, что в наши дни я в основном использую C++

Почему вы используете «if (x / *! = 0 * /)»? Чтобы генерировать меньше (а значит, быстрее) кода? Есть ли разница в коде, созданном для «if (x)» и «if (x! = 0)»?

Adrian Pronk 01.01.2009 15:35

Читаемость, больше всего на свете. Когда я был моложе, я делал некоторые уроки, и это немного помогло новичкам (если (x)) может сбивать с толку, как ни удивительно. Я всегда осторожен с логикой :-) Я не думаю, что он генерирует меньше кода, в любом случае недостаточно, чтобы быть значимым :-)

billybob 02.01.2009 02:04

VBScript? Этот фрагмент кода объявляет вариант, поэтому bFlag равен нулю, что фактически является ложью.

Dim bFlag
If bFlag Then

Мне это не нравится. Таким образом, даже в VB с возможностью более конкретных объявлений я обнаруживаю, что выражаюсь явно независимо от типа.

Dim bFlag As Boolean
If bFlag = False Then

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

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

if ( var )
if ( $var )

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

$shouldDoSomething = ( defined $var and $var ne '' ) ? 1 : 0;

if ( $shouldDoSomething ) {
    // Handle this case.
}

Это может немного очистить код. Также полезно, если вы собираетесь использовать это условие более одного раза. На самом деле, я считаю, что это случается довольно часто. Кроме того, мне кажется, что приведенное выше гораздо более читабельно, чем встроенное:

if ( defined $var and $var ne '' ) {
    // Handle this case.
}

? 1: 0 не нужен и, на мой взгляд, запутан.

ysth 01.01.2009 14:23

Вы правы, в данном конкретном примере это не нужно. Я добавил его, чтобы разобраться с тем, что «правда и ложь в Perl» являются «таким минным полем», упомянутым в вопросе. С помощью этого кода вы будете знать, что $ shouldDoSomething всегда будет либо 0, либо 1.

Beau Simensen 01.01.2009 14:44
Ответ принят как подходящий

Мне нравится, что мои if имеют смысл при чтении вслух:

if (is_it_happening) ...
if (number_of_sheep != 0) ...
if (pointer_to_something != NULL) ...

Константы на LHS пожалуйста :)

JaredPar 01.01.2009 18:12

@JaredPar: константы слева или справа - это тема для другого потока

Adam Rosenfield 01.01.2009 18:45

константы слева не позволяют прочитать его вслух.

shoosh 01.01.2009 22:42

@Shy 0! = Number_of_sheep (ноль - это не количество овец) звучит для меня нормально: P

Ólafur Waage 01.01.2009 23:58

Для мастера-джедая это особенно хорошо.

che 02.01.2009 00:02

че: Обидно, что здесь нельзя модерировать комментарии как +1 Забавно, как на Slashdot. Я бы поддержал твою.

Tamas Czinege 03.01.2009 01:37

Константы в LHS имели смысл, когда компиляторы были мертвыми. Теперь они помечают предупреждение, если вы пытаетесь назначить его внутри if, и у всех должен быть включен параметр «рассматривать предупреждения как ошибку».

Jesse Weigert 19.03.2009 05:44

@Jesse: Я так думаю. Константы в левой части были созданы для предотвращения ошибок программиста. В английском языке константы всегда находятся в правой части уравнения. «Мой бензобак пуст», «Ваша рубашка зеленая», «Если указатель не ПУСТОЙ» и т. д.

dreamlax 19.03.2009 05:48

@shoosh, это правда только если ты англичанин.

Pacerier 13.05.2015 07:30

В Javascript (про другие динамические языки не знаю)

if (x) 

а также

if (x != 0)

означают разные вещи. Я буду использовать первое, когда я ожидаю, что x будет содержать ссылку на объект или строку, длина которой не должна быть нулевой. Это достаточно известная идиома.

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

Но опять же, этот стиль настолько популярен, что, вероятно, не так уж важно, но, работая с C#, я пишу свой код C++ в этом стиле:

Boolean или int, который в основном является логическим:

if (val)

Истинное целое число с важностью более чем истина / ложь:

if (val != 0)

Указатель какой-то:

if (val != NULL)

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

Очень часто использую:

 if (x) {
       DoSomething;
       DoSomething2;
     }

Потому что это меньше письма, а книга, в которой читается, говорит:

Few good programmers use form if (x!=0), they use if (x).

Но иногда используют и другую форму:

if (x!=0) 

HNY! :-)

В какой книге это сказано?

erikkallen 01.01.2009 23:08

Я удивлен, что никто не упомянул другой вариант, который защищал стандарты кодирования моего бывшего работодателя:

if ( 0 != x );

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

Это стиль, который я использовал с тех пор в моем C / Perl / C++ / VB.Net с тех пор (очевидно, что в C# вопрос становится спорным, который фактически не допускает сценарий if (x) (если, конечно, x на самом деле не является логическим).

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

Rowland Shaw 05.01.2009 21:46

Согласны, вниз избиратели должны комментировать!

Terry G Lorber 19.03.2009 05:47

Сегодня получил еще один необъяснимый голос против ...

Rowland Shaw 13.09.2009 18:45

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

Nathan Fellman 29.12.2009 11:03

Но это также выражение предпочтений, когда есть три варианта. возможно, ответом должно было быть «ни то, ни другое», что менее полезно

Rowland Shaw 29.12.2009 18:09

Константы на LHS абсурдны и предполагают недостаток интеллекта у других кодировщиков и у вас самих.

James Morris 30.04.2010 17:53

В C# было явно запрещено писать

if (x){}

если x не является логическим типом. Неявного преобразования в bool из большинства других типов нет.

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

Когда я использую его для логических переменных, я твердо верю в легко читаемые имена. Я обычно называю такие логические переменные именами, начинающимися с «is», «has» или чего-то подобного.

В Perl if (defined $var and $var ne '') и if ( $var) НЕ эквивалентны. Попробуйте с $var=0. И наоборот, если вы тестируете $var!=0, все строки, которые не могут быть преобразованы в числа, не пройдут тест (с предупреждением, если они у вас включены).

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

Обычно я просто пишу if ( $var) и позволяю Perl позаботиться об этом. Я считаю, что это легче читать, и это самый распространенный стиль в Perl.

На самом деле, очень часто правильный тест оказывается if ( defined $var). Вот где пригодится новый оператор Perl // (в версии 5.10). $var= $val // $default или часто $var //= $default, где $var получит $default, только если $val (соответственно $var) - это undef.

Вот почему я сказал: «Истина и ложь в Perl - такое минное поле». Обычно я хочу знать, "определены ли $ var и $ var ne ''". Обычно я не хочу, чтобы тест возвращал false, если "$ var eq '0'"

Adrian Pronk 18.01.2009 23:35

Я обычно предпочитаю if (var) или if ($var), если var используется как логическое, даже если в языке нет такого типа.

Я очень не люблю такие конструкции, как if (!strcmp(...)) или if (var == true). Первый пытается быть слишком умным, второй слишком тупым - хотя он хорошо масштабируется до if ((var == true) == true), ... ;-)

Некоторые языки, такие как Perl и C++, предоставляют дополнительную или даже определяемую пользователем интерпретацию правильности. Если преобразование в логическое значение кажется слишком волшебным, помните, что это в основном просто is_true(var) или var.booleanValue(), или что-то в этом роде за сценой, просто более сжатый синтаксис.

Что касается вашего вопроса, мне нравится формулировать условия в позитивном ключе. Вместо

if (!condition) {
    g();
}
else {
    f();
}

я предпочитаю

if (condition) {
    f();
}
else {
    g();
}

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

// explain reason for condition here
if (!condition) {
    f();
}

Я предпочитаю сформулировать это как

if (condition) {
    // explain condition here
}
else {
    f();
}

Я предпочитаю удобочитаемость, как и большинство людей, мне нравится иметь возможность сканировать свой код и читать его, не слишком много думать, это идет рука об руку, хотя и с хорошо названными именами переменных. Если ваши имена переменных звучат так, как будто это должен быть простой if (isPurchasable), я использую его, но он относится к номеру, дате или аналогичному стилю, я использую if (stock > 0).

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

if (isPurchasable && stock > 0 && credit >= cost && !reserved) { 
     // Checks to see if customer can purchase product.
}

читаемый код улучшает ремонтопригодность и понимание кода. Код предназначен для людей. IL или бинарный - для компьютеров.

Matthew 01.01.2009 22:03

Стоит ли вам действительно быть программистом, если вы не хотите слишком много думать !?

James Morris 30.04.2010 17:54

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

stuartloxton 25.05.2010 23:30

Для скаляров числовых значений я обычно пишу if ( $num_foo ), когда $num_foo находится под моим контролем. Если это пользовательский ввод или полученный извне, я либо сначала нумерую его, либо подробно описываю тест. Это зависит от множества факторов. Главный критерий - когда и как удобно работать с неопределенными значениями, чтобы избежать предупреждений.

Чтобы проверить непустую строку, я писал if ( $foo ), потому что правильное заклинание - это слишком много набирать:

if ( defined $foo and length $foo )

Но меня не устраивало такое положение вещей, поэтому Я инициировал изменение поведения length undef в Perl 5.12 выдает предупреждение и возвращает 0 до Perl 5.10 включительно. В 5.12 он просто молча вернет undef. Поэтому в небулевых контекстах вы все равно получаете предупреждение, оно происходит только после оценки вызова length, а не до него. Но в логических контекстах предупреждения нет, поэтому проверку на наличие непустой строки намного проще сделать правильно:

if ( length $foo )

На мой взгляд, простота лучше всего.

Чем проще вы сделаете код, тем лучше. Кроме того, тем меньше вероятность того, что вы совершите ошибку. Поэтому я бы использовал

if (var)

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

Мне не всегда это удается, но я стараюсь использовать

if (0 != var)

так что это соответствует оборонительному стилю

if (0 == var)

Я предпочитаю голый:

if ($canDo) {
}

вместо чего-то вроде:

if ($canDo == true) {
}

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

my($canDo) = !0;

к

my($canDo) = 1;

Последнее сбивает с толку; зачем назначать дискретное значение логическому?

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

Все очень просто. if ( var ) проверяет правдивость. if ( var != 0 ) проверяет, что это не номер 0. ОНИ НЕЗАМЕНЯЕМЫЕ! Есть три причины.

Во-первых, использовать if ( var != 0 ) для проверки истины сложнее. Там просто больше, чтобы прочитать и понять. Вы должны понять, что != и 0 - это идиома, означающая «верно». Не имея четкого визуального рисунка, вам придется немного изучить его, чтобы понять, что это не то же самое, что if ( var == 0). Это тонкое различие, но о нем стоит упомянуть. Тот факт, что стиль if ( 0 != var ) существует, внушает доверие. Лучше просто устранить проблему и для правды использовать if ( var ).

Во-вторых, что более важно, намерение должно быть ясным. Вы проверяете истину или проверяете число (или его отсутствие)? if ( var ) проверяет истину, if ( var != 0 ) проверяет число. Чтобы определить что-либо еще, требуется знание авторского стиля, которого, мы должны предположить, не знает программист по обслуживанию.

В-третьих, здесь есть предположение о значениях истинных, ложных и числовых операторов, которые могут работать на одних языках, а не на других. В Perl и, как мне кажется, в Javascript пустая строка неверна. Многие операторы возвращают пустую строку за ложь. Так что проверка правды с if ( var != 0 ) приводит к предупреждению. Это становится более очевидным, когда вы делаете что-то более наивное, например if ( var == 1 ), чтобы обозначить истину, явно опасное предположение. Мне кажется, что многие молодые программисты пишут это и, в свою очередь, пишут функции, возвращающие нечетные, но верные числа, для наказания за подобные вещи. Или, когда я в настроении пожертвовать, я продезинфицировал возвращаемое значение с помощью return var ? 1 : 0.

В соответствующем примечании Perl вернет последнее вычисленное выражение из подпрограммы, поэтому на самом деле нет необходимости писать return. Объедините это с представлением людей о том, что явно return работает медленнее, и вы получите множество людей, злоупотребляющих этим фактом.

sub set {
    my( $self, $key, $value ) = @_;

    $self->{$key} = $value;
}

set вернет $value. Это было задумано? Я не знаю. Я точно знаю, что кто-то начнет на это полагаться. И программист обслуживания не будет знать, могут ли они это изменить. Поэтому мне нравится явно помещать возврат в каждую нетривиальную подпрограмму.

sub set {
    my( $self, $key, $value ) = @_;

    $self->{$key} = $value;
    return;
}

В этом случае я решил, что set пока ничего не вернет, и это решение будет совершенно понятно как читателю, так и пользователю.

Полный код поддерживает этого чувака.

James McMahon 19.03.2009 05:48

Мне нравятся твои рассуждения, я никогда не думал об этом так.

JimDaniel 19.03.2009 06:14

@nemo Я вырос на этой книге. :)

Schwern 22.03.2009 20:38

+1 для вашей идиомы, чтобы включить явный возврат void, когда подпрограмма не предназначена для возврата ничего. Я никогда не думал об этом ракурсе. Кстати, мой исходный вопрос гласит: «... когда я имел в виду, если var! = 0», поэтому я не предполагал, что разные формы эквивалентны, просто в некоторых ситуациях одну можно заменить другой для лучшей читаемости.

Adrian Pronk 01.08.2010 05:23

Я считаю, что if (X) {/ * ... * /} намного легче читать (по крайней мере, на C).

Если я не ожидаю, что кто-то еще прочитает код, я бы использовал короткий. Если я ожидаю, что кто-то действительно прочитает мой код, я бы подумал об использовании длинной формы для удобства чтения.

Кто-то всегда собирается прочитать код.

Adriano Varoli Piazza 08.01.2009 22:26

На мой взгляд, лучше if (var != 0).

Мне нравятся конструкции Python:

if var:
    return "I like the way I do it!"

Это просто например ;-)

Если у вас есть int-bool в C, который уже содержит флаг (а не счетчик), и вы тестируете его с помощью «if (var! = 0)», где он заканчивается? Разве «if ((var! = 0)! = 0)» не было бы даже лучше? :-)

Кто-то читал Геделя, Эшера и Баха - или пропустил это и сразу перешел к Льюису Кэрроллу :-)

Dan Breslau 19.03.2009 05:56

Я никогда не читал ни первого, ни чего-либо другого. Об этом мне рассказал мой первый курс CS проф.

Anonymous Coward 19.03.2009 06:55

Ну, я не сказал, что это ты :-) Но я рекомендую их обоих.

Dan Breslau 19.03.2009 07:15

Есть языки, на которых у вас нет выбора. В Specman, например, нельзя писать:

var x: uint;

if (x) {
    bla
};

Но вы может делаете:

var x: uint;

if (x != 0) {
    bla
};

или же

var x: bool;

if (x) {
    bla
};

Однако делать нельзя:

var x: bool;

if (x != 0) {
    bla
};

Потому что вы не можете сравнивать логическое значение с целым числом.

Переходя с C и Perl, я всегда думал, что это раздражает, пока я действительно не начал много писать на Specman. Код просто понятнее.

Другие вопросы по теме