Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

Оценка короткого замыкания , минимальная оценка или оценка Маккарти (после Джона Маккарти ) - это семантика некоторых логических операторов в некоторых языках программирования, в которых второй аргумент выполняется или оценивается только в том случае, если первого аргумента недостаточно для определения значения выражение: когда первый аргумент ANDфункции оценивается как false, общее значение должно быть false; и когда первый аргумент ORфункции оценивается как true, общее значение должно быть true.

В языках программирования с отложенным вычислением ( Lisp , Perl , Haskell ) обычные логические операторы являются короткозамкнутыми. В других ( Ada , Java , Delphi ) доступны как короткие замыкания, так и стандартные логические операторы. Для некоторых логических операций, таких как исключающее или (XOR), короткое замыкание невозможно, потому что для определения результата всегда требуются оба операнда.

Операторы короткого замыкания, по сути, являются управляющими структурами, а не простыми арифметическими операторами, поскольку они не являются строгими . В терминах императивного языка (особенно C и C ++ ), где важны побочные эффекты, операторы короткого замыкания вводят точку последовательности - они полностью оценивают первый аргумент, включая любые побочные эффекты , перед (необязательно) обработкой второго аргумента. Алгол 68 использует процедуры для достижения определяемых пользователем операторов и процедур короткого замыкания.

Использование операторов короткого замыкания критиковалось как проблематичное:

Условные связки - « канд » и « кор » для краткости ... менее невинны, чем может показаться на первый взгляд. Например, cor не распределяет по cand : compare

плавиковый шпат В) кор С скор С) плавиковый шпаткор С);

в случае ¬A ∧ C второе выражение требует, чтобы B был определен, а первое - нет. Поскольку условные связки усложняют формальные рассуждения о программах, их лучше избегать.

Определение [ править ]

В любом языке программирования, который реализует оценку короткого замыкания, выражение эквивалентно условному выражению , а выражение эквивалентно . В любом случае x оценивается только один раз.x and y if x then y else xx or yif x then x else y

Приведенное выше обобщенное определение подходит для языков со слабой типизацией, которые имеют более двух истинностных значений True и False, где операторы короткого замыкания могут возвращать последнее вычисленное подвыражение. В приведенной ниже таблице это называется «последним значением». Для строго типизированного языка выражение упрощается до логического случая и соответственно.if x then y else falseif x then true else y

Приоритет [ править ]

Несмотря на то, ANDимеет приоритет над ORна многих языках, это не является универсальным свойством оценки короткого замыкания. Пример два оператора принимает тот же приоритет , и будучи левоассоциативным друг с другом является POSIX оболочка списка команд синтаксиса «s. [2] ( §2.9.3 )

Следующий простой вычислитель с написанием слева направо обеспечивает приоритет ANDover с ORпомощью a continue:

функция short-circuit-eval ( операторы , значения ) let  result  : = True для каждого ( op , val ) в ( операторы , значения ): if  op = "AND" && result = False продолжить  else if  op = "OR" && result = True обратного  результата  еще  результат  : = VAL  обратного  результата

Формализация [ править ]

Логика короткого замыкания, с побочными эффектами или без них, была формализована на основе условного оператора Хоара . Результатом является то, что операторы без короткого замыкания могут быть определены из логики короткого замыкания, чтобы иметь ту же последовательность оценки. [3]

Поддержка общих языков программирования и сценариев [ править ]

1 ABAP и APL не имеют отдельного логического типа.
2 При перегрузке операторы &&и ||готовы возвращать любой тип.
3 Это применимо только к выражениям, оцениваемым во время выполнения, static ifи static assert. Выражения в статических инициализаторах или константах манифеста используют активное вычисление.
4 Операторы Fortran не являются ни коротким замыканием, ни стремлением: спецификация языка позволяет компилятору выбрать метод для оптимизации.
5 ISO / IEC 10206: 1990 Extended Pascal допускает, но не требует, короткое замыкание.
6 ISO / IEC 10206: 1990 Extended Pascal поддерживает and_thenи or_else. [9]
7Smalltalk использует семантику короткого замыкания до тех пор, пока аргументом and:является блок (например, false and: [Transcript show: 'Wont see me']).
8 языков BASIC, которые поддерживали операторы CASE, сделали это с помощью системы условной оценки, а не в виде таблиц переходов, ограниченных фиксированными метками.
9 Delphi и Free Pascal по умолчанию используют оценку короткого замыкания. Это может быть изменено параметрами компилятора, но, похоже, не используется широко.

Обычное использование [ править ]

Избегайте нежелательных побочных эффектов второго аргумента [ править ]

Обычный пример с использованием языка на основе C :

int  denom  =  0 ; if  ( denom  ! =  0  &&  num  /  denom ) {  ...  // гарантирует, что вычисление num / denom никогда не приведет к ошибке деления на ноль }

Рассмотрим следующий пример:

int  a  =  0 ; если  ( а  ! =  0  &&  myfunc ( b )) {  do_something (); }

В этом примере оценка короткого замыкания гарантирует, что myfunc(b)никогда не вызывается. Это потому, что a != 0оценивается как ложь . Эта функция позволяет использовать две полезные программные конструкции.

  1. Если первое подвыражение проверяет, нужны ли дорогостоящие вычисления, и проверка дает ложное значение , можно исключить дорогостоящие вычисления во втором аргументе.
  2. Это разрешает конструкцию, в которой первое выражение гарантирует условие, без которого второе выражение может вызвать ошибку времени выполнения .

Оба показаны в следующем фрагменте кода C, где минимальная оценка предотвращает как разыменование нулевого указателя, так и выборку излишней памяти:

bool  is_first_char_valid_alpha_unsafe ( const  char  * p ) {  return  isalpha ( p [ 0 ]);  // SEGFAULT очень возможно с p == NULL }bool  is_first_char_valid_alpha ( const  char  * p ) {  return  p  ! =  NULL  &&  isalpha ( p [ 0 ]);  // 1) нет ненужного выполнения isalpha () с p == NULL, 2) нет риска SEGFAULT }

Идиоматическая условная конструкция [ править ]

Поскольку минимальная оценка является частью семантического определения оператора, а не (необязательной) оптимизацией, многие шаблоны кодирования [ какие? ] стали полагаться на него как на краткую (если идиоматическую) условную конструкцию. Примеры включают:

Идиомы Perl :

some_condition  или  умереть ;  # Прервать выполнение, если some_condition ложно some_condition  и  die ;  # Прервать выполнение, если some_condition истинно

Идиомы оболочки POSIX : [10]

modprobe -q some_module &&  echo  "модуль some_module установлен"  ||  echo  "some_module не установлен"

Эта идиома предполагает, что echoэто невозможно.

Возможные проблемы [ править ]

Непроверенное второе условие приводит к невыполненным побочным эффектам [ править ]

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

если  ( выражениеA  &&  myfunc ( b ))  {  do_something (); }

if myfunc(b)предполагается выполнить некоторую требуемую операцию независимо от того do_something(), выполняется ли она, например, выделение системных ресурсов, и expressionAоценивается как false, то myfunc(b)не будет выполняться, что может вызвать проблемы. В некоторых языках программирования, таких как Java , есть два оператора, один из которых использует минимальную оценку, а другой - нет, чтобы избежать этой проблемы.

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

Снижение эффективности из-за ограничений оптимизации [ править ]

Короткое замыкание может привести к ошибкам в прогнозировании переходов на современных центральных процессорах (ЦП) и резко снизить производительность. Ярким примером является высоко оптимизированный луч с выровненным по оси кодом пересечения прямоугольника при трассировке лучей . [ требуется пояснение ] Некоторые компиляторы могут обнаруживать такие случаи и генерировать более быстрый код, но семантика языка программирования может ограничивать такую ​​оптимизацию. [ необходима цитата ]

Примером компилятора, неспособного оптимизировать для такого случая, является виртуальная машина Hotspot Java от 2012 года [12].

См. Также [ править ]

  • Состояние безразличия

Ссылки [ править ]

  1. Эдсгер В. Дейкстра «О несколько неутешительной переписке», EWD1009-0, 25 мая 1987 г., полный текст
  2. ^ "Командный язык оболочки" . pubs.opengroup.org .
  3. ^ Ян А. Бергстра, А. Понсе, DJC Staudt (2010). «Логика короткого замыкания». arXiv : 1010.3674 [ cs.LO ].CS1 maint: использует параметр авторов ( ссылка )
  4. ^ Стандарт ISO / IEC 9899, ​​раздел 6.5.13
  5. ^ Проект ISO / IEC IS 14882.
  6. ^ https://wiki.python.org/moin/BitwiseOperators
  7. ^ "std :: ops - Ржавчина" . doc.rust-lang.org . Проверено 12 февраля 2019 .
  8. ^ ETSI ES 201 873-1 V4.10.1, раздел 7.1.4
  9. ^ "and_then - Руководство GNU Pascal" . Gnu-pascal.de . Проверено 24 августа 2013 .
  10. ^ "Что означает || в bash?" . stackexchange.com . Проверено 9 января 2019 .
  11. ^ «Ссылочная прозрачность, определенность и разворачиваемость» (PDF) . Itu.dk . Проверено 24 августа 2013 .
  12. ^ Вассерман, Луи. «java - В каких случаях лучше использовать безусловное И (& вместо &&)» . Переполнение стека .