Информация об изменениях

Сообщение Re[4]: if (a == true) от 03.09.2024 21:05

Изменено 03.09.2024 21:10 Alekzander

Re[4]: if (a == true)
Здравствуйте, Sinclair, Вы писали:

A>>Это хуже йодинга: смысл перестановка меняет незначительно лишь, а инверсия страшная тут.

S>Смысл меняется, и очень-очень сильно. true обычно равно 0xFFFFFFFF.
S>При этом if(a) компилируется/интерпретируется как if(a!=0), подразумевая любое ненулевое значение.
S>В итоге, если в a попадает 42, то if(a == true) пройдёт мимо, а if(a != false) зайдёт внутрь. Как и if(a).
S>Так что, возможно пишет if(a == true) вовсе не идиот.
S>Может быть, a имеет тип "недоперечисления", которое организовано так, что -1 = started; 0 = stopped; 1 = starting; 2 = stopping; 16 = error. Для совместимости с совсем древним кодом, который написан для времён с двумя статусами сервиса, которые он проверял через if(!service->status).
S>А теперь нам нужен код, который убеждается, что сервис именно что запущен.

Я понял kov_serg'а так, что он предлагает в качестве альтернативы йода-сравнению (if (true == a)) инверсию (if (a != false)). Ведь при инверсии тоже нельзя нечаянно присвоить значение, перепутав = и == (помешает !), зато не придётся переставлять переменную в конец. Может, конечно, понял неправильно.

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

A>>Если тип не bool, они в таких случаях пишут каст плюс == true.

S>Даже если тип bool, не всегда он сформирован честным образом из констант true, false, и булевых операций. Даже в дотнете я налетал (правда, из-за бага в моём же unsafe коде) на то, что булевая логика на SIMD дала не true, а non-false результат. В итоге, код с if(a) прекрасно работал, а вот тесты, которые сравнивали вычисленный массив булеанов с референс-значениями, фейлились.

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

Но любители буля скажут, наверно, что те, кто не обеспечил строгий true и false, нарушили контракт. И тоже будут по-своему правы.

A>>Боюсь, не совсем понимаю. service.IsStarted это почти наверняка функция (аксессор). И?

S>Всё зависит от системы типов в языке.
S>Например, if(service.IsStarted) внезапно убеждается, что адрес этой функции ненулевой. И если ваш язык — не typescript, то не всякий компилятор будет вам намекать на отсутствие скобок.
S>А вот if(service.IsStarted == true) уже имеет некоторые шансы нарваться на no operator== defined for the arguments of type 'bool (*check)()' and 'bool'.
S>С другой стороны, это недостаточно каргокультно.
S>По классике, нужно писать вот так:
S>
S>if(true == service.IsStarted())
S>


Теперь понял. Ну, смотря как делать свойства в языке-принимающем-адрес-за-true. Если их делать аналогично шарповским, через __declspec (поддерживается в clang с опцией компилятора -fdeclspec и MSVC), то перепутать нельзя, не скомпилируется:

https://gcc.godbolt.org/z/fdW74ocfG

Обе части 1 и 2 должны соответствовать.

Глобальная же функция всего лишь даёт ворнинг. Что неприятно, да. То есть, как подстраховка от (забыли скобки) x (проигнорировали ворнинг) x (глобальная функция) x (сигнатура: возвращает bool, не имеет параметров) x (в норме всегда возвращает true, и не ловится при первом же запуске) добавление == true действительно помогает
Re[4]: if (a == true)
Здравствуйте, Sinclair, Вы писали:

A>>Это хуже йодинга: смысл перестановка меняет незначительно лишь, а инверсия страшная тут.

S>Смысл меняется, и очень-очень сильно. true обычно равно 0xFFFFFFFF.
S>При этом if(a) компилируется/интерпретируется как if(a!=0), подразумевая любое ненулевое значение.
S>В итоге, если в a попадает 42, то if(a == true) пройдёт мимо, а if(a != false) зайдёт внутрь. Как и if(a).
S>Так что, возможно пишет if(a == true) вовсе не идиот.
S>Может быть, a имеет тип "недоперечисления", которое организовано так, что -1 = started; 0 = stopped; 1 = starting; 2 = stopping; 16 = error. Для совместимости с совсем древним кодом, который написан для времён с двумя статусами сервиса, которые он проверял через if(!service->status).
S>А теперь нам нужен код, который убеждается, что сервис именно что запущен.

Я понял kov_serg'а так, что он предлагает в качестве альтернативы йода-сравнению (if (true == a)) инверсию (if (a != false)). Ведь при инверсии тоже нельзя нечаянно присвоить значение, перепутав = и == (помешает !), зато не придётся переставлять переменную в конец. Может, конечно, понял неправильно.

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

A>>Если тип не bool, они в таких случаях пишут каст плюс == true.

S>Даже если тип bool, не всегда он сформирован честным образом из констант true, false, и булевых операций. Даже в дотнете я налетал (правда, из-за бага в моём же unsafe коде) на то, что булевая логика на SIMD дала не true, а non-false результат. В итоге, код с if(a) прекрасно работал, а вот тесты, которые сравнивали вычисленный массив булеанов с референс-значениями, фейлились.

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

Но любители буля скажут, наверно, что те, кто не обеспечил строгий true и false, нарушили контракт. И тоже будут по-своему правы.

A>>Боюсь, не совсем понимаю. service.IsStarted это почти наверняка функция (аксессор). И?

S>Всё зависит от системы типов в языке.
S>Например, if(service.IsStarted) внезапно убеждается, что адрес этой функции ненулевой. И если ваш язык — не typescript, то не всякий компилятор будет вам намекать на отсутствие скобок.
S>А вот if(service.IsStarted == true) уже имеет некоторые шансы нарваться на no operator== defined for the arguments of type 'bool (*check)()' and 'bool'.
S>С другой стороны, это недостаточно каргокультно.
S>По классике, нужно писать вот так:
S>
S>if(true == service.IsStarted())
S>


Теперь понял. Ну, смотря как делать свойства в языке-принимающем-адрес-за-true. Если их делать аналогично шарповским, через __declspec (поддерживается в clang с опцией компилятора -fdeclspec и MSVC), то перепутать нельзя, не скомпилируется:

https://gcc.godbolt.org/z/fdW74ocfG

Обе части 1 и 2 должны соответствовать.

(А по стандарту их надо делать через такую задницу, что лучше вообще не делать).

Глобальная же функция всего лишь даёт ворнинг. Что неприятно, да. То есть, как подстраховка от (забыли скобки) x (проигнорировали ворнинг) x (глобальная функция) x (сигнатура: возвращает bool, не имеет параметров) x (в норме всегда возвращает true, и не ловится при первом же запуске) добавление == true действительно помогает