Когда плохая оценка короткого замыкания?

12

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

Теперь я начинаю работу над проектами, требующими VB.net, и я вижу, что он предоставляет оба способа с точки зрения AND и ANDALSO . Первый не закорачивает, а второй делает.

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

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

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

Кит Рамос
источник

Ответы:

5

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

if not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

В других случаях вы не хотите оценивать какие-либо из оставшихся терминов, если более ранняя оценка возвращает false.

if IsAirborne() and not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

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

VAL's ANDALSO является четким и, кажется, попыткой сделать практику более приемлемой.

Как указывает JimmyJames в своем ответе, при оценке короткого замыкания могут быть ощутимые последствия для производительности. Языки, которые не предоставляют механизм, всегда оценивают каждый термин выражения, в то время как те, которые предоставляют его, могут генерировать дополнительные операторы ветвления. В любом случае, многое зависит от количества этапов обработки, необходимых для оценки каждого из терминов, а также от архитектуры компилятора и процессора. Обычно вы не заботитесь о таких вещах до тех пор, пока у вас не возникнет серьезное узкое место в коде, и вам не придется решать, как его устранить. Любые правила «делать или не делать», касающиеся разрешения оценки короткого замыкания в вашем коде, будут иметь примерно равную вероятность вызвать более медленный код, а ранняя оптимизация может быть пустой тратой времени, поэтому всегда измеряйте, а затем оптимизируйте.

jwdonahue
источник
4
Хотя это на самом деле правильно, это не очень хороший дизайн.
Роберт Харви
2
@RobertHarvey, я не могу написать систему управления, которая не имеет побочных эффектов, и я не могу правильно управлять системой, если я не реагирую на результаты. Другими словами, преодолеть это;).
Jwdonahue
7
Нет, но вы можете присваивать результаты этих побочных функций булевым переменным, проверять эти переменные в своем ifсостоянии и по-прежнему иметь короткое замыкание. Я согласен с тем, что это, в некотором смысле, стилистическое различие, но оно имеет то преимущество, что делает вещи кристально чистыми.
Роберт Харви
3
@jwdonahue Можно использовать «громкие слова», если риск путаницы невелик. Риск путаницы и упущения определенных нюансов такого блока кода чрезвычайно высок и может быть катастрофическим для логики. Заставить читателя думать никогда не стоит.
jpmc26
5
«Некоторые термины в логическом выражении могут иметь побочные эффекты». Хотя это вступительное утверждение и является правильным, я чувствую, что в этом ответе не говорится о том, что полагаться на побочные эффекты плохо . На самом деле, гораздо хуже, чем полагаться на оценку короткого замыкания для предотвращения ложных оценок. То, что этот ответ действительно предлагает, может быть плохой формой.
Aroth
20

По-видимому, ваш вопрос не в том, является ли короткое замыкание хорошим или плохим в целом, а в том, почему VB.NET предоставляет операторам и без него. Имея это в виду, ответ на

когда плохая оценка короткого замыкания?

это просто: когда это нарушает обратную совместимость .

Хорошо, теперь вы можете сказать, что VB.NET не очень обратно совместим со старым VB6 или VBA, однако, по крайней мере, некоторые части языка таковы. Решение Microsoft о сохранении старой семантики «И» и «ИЛИ» (без короткого замыкания) сделало огромную категорию ошибок менее вероятной при переносе старых программ VB в VB.NET.

С другой стороны, дизайнеры языка VB.NET, вероятно, поделились своим мнением о том, что короткое замыкание - это хорошо. Когда я правильно помню, первые предварительные версии VB.NET предоставляли операторам И или ИЛИ короткое замыкание, но отзывы разработчиков, должно быть, были настолько плохими, что MS отозвала это решение до появления VB.NET 1.0. Поэтому дизайнеры решили реализовать его с точки зрения новых ключевых слов ANDALSOи ORELSEкак компромисс между обратной совместимостью и полезностью.

ИМХО это было хорошее решение. Мне пришлось портировать несколько старых программ за последнее десятилетие, и не нужно было проводить тяжелый анализ воздействия для каждого логического выражения, включая AND и / или OR (каламбур), что значительно облегчило эту задачу и стало более экономичным. С другой стороны, всякий раз, когда мне нужно написать новое логическое выражение в VB.NET, мой выбор по умолчанию для операторов - это формы короткого замыкания, к которым я привык из C, C ++, C # и т. Д., И это позволяет мне написать несколько идиом в более сжатой форме (даже если ANDALSO нужно еще 4 символа для ввода).

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

Док Браун
источник
Хорошо, это квалифицируется как напыщенная речь, и связь с марсианскими наушниками, похоже, вообще не связана.
Jwdonahue
6
@jwdonahue: я понятия не имею, почему вы думаете, что это напыщенная речь, а совсем наоборот. А статья о марсианских гарнитурах - о том, почему некоторые дизайнерские решения в разработке программного обеспечения, принятые несколько десятилетий назад, не могут быть легко отменены после того, как рассматриваемый компонент, язык или API достигли базы пользователей определенного размера. Разве не так сложно понять аналогию? В прошлом VB6 был очень популярен, и я уверен, что еще сотни тысяч компаний в мире имеют критически важные приложения, работающие на VB6 или VBA.
Док Браун
Я не совсем понимаю, как на самом деле подходит статья "Марсианские головные уборы". Для обеспечения совместимости между X и Y (например, гайками и болтами) необходимо иметь отдельные стандарты для X и Y, чтобы гайка для наихудшего случая соответствовала болту чуть хуже указанного, и наоборот. Следует попытаться написать спецификации, чтобы избежать ненужных дорогостоящих затяжек гаек или болтов или ненужного наклона между гайками и болтами, но указание обеих половин по отдельности позволяет обеспечить совместимость гораздо более надежно, чем попытка получить одну спецификацию служить обеим сторонам.
суперкат
3
@supercat: речь идет о наличии и использовании уже триллионов гаек (или строк кода VB6), и теперь болты (или в этом случае компилятор VB) будут заменены новым поколением. Если существующие гайки подходят только для неметрических болтов, экономически невыгодно использовать только новые метрические системы болтов.
Док Браун
tl; dr: VB является диалектом BASIC, языка, датируемого 1964 г., и в BASIC Andоперация не замыкается накоротко, ни в SQL (1974), ни в FORTRAN (1956), ни в Pascal (1970).
Бен
3

когда плохая оценка плохого?

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

πάντα ῥεῖ
источник
1

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

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

JimmyJames
источник
Я думаю, что до сих пор вы можете оптимизировать только логическое утверждение, в конечном итоге вам придется брать ветки.
Jwdonahue
@jwdonahue Я не понимаю твою точку зрения. Сожалею.
JimmyJames
Мы говорим о комбинаторной логике здесь. Оценка короткого замыкания или нет, у вас есть одно или несколько условий, которые должны оцениваться в зависимости от результата более раннего срока. Следовательно, ветвление вовлечено.
Jwdonahue
1
@jwdonahue Конечно, но каждое короткое замыкание - это дополнительная ветвь. В некоторых сценариях выполнение двух выражений (например) выполняется быстрее, чем проверка результата первого перед выполнением второго, даже если часто случается, что второе не имеет значения. Опять же, это редко важно. Случай, который кто-то сделал мне для этого, был для таких вещей, как умножение матриц, где у вас есть много простых оценок.
JimmyJames
1
Я обновил свой ответ с благодарностью вам.
Jwdonahue
0

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

C и C ++ имеют побитовые операции & и | которые на практике дают вам операции без короткого замыкания. И компиляторы могут свободно оценивать их так, как им нравится, если это не имеет заметного значения.

gnasher729
источник
@Deduplicator: Как уже отмечалось, Паскаль не определил, использует ли И / ИЛИ оценку короткого замыкания. Это значит «не зная».
суперкат