Оценка короткого замыкания

редактировать

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

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

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

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

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

(A cand B) cor C с (A cor C) cand (B cor C);

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

Эдсгер В. Дейкстра
Содержание
  • 1 Определение
    • 1.1 Приоритет
    • 1.2 Формализация
  • 2 Общая поддержка языки программирования и сценариев
  • 3 Обычное использование
    • 3.1 Избежание нежелательных побочных эффектов второго аргумента
    • 3.2 Идиоматическая условная конструкция
  • 4 Возможные проблемы
    • 4.1 Непроверенное второе условие приводит к невыполненным побочным эффектам
    • 4.2 Снижение эффективности из-за ограничений оптимизации
  • 5 См. Также
  • 6 Ссылки
Определение

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

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

Приоритет

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

Следующий простой слева -вправо вычислитель обеспечивает приоритет Инад ИЛИс помощью функции continue:

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

Формализация

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

Поддержка общих языков программирования и сценариев
Логические операторы на разных языках
ЯзыкОператоры нетерпения Операторы короткого замыканияТип результата
Расширенное программирование бизнес-приложений (ABAP )нети, orBoolean
Ada и, or, а затем, или ещеBoolean
ALGOL 68 и,, ∧; или, ∨andf, orf (оба определены пользователем)Boolean
APL , , (nand), (nor) и т. д.: AndIf, : OrIfBoolean
awk none, ||Boolean
Bash none, ||Boolean
C, Objective-C none, ||, ?int (,||), зависимый от opnd (?)
C ++ none, ||, ?логический (,||), зависимый от opnd (?)
C# , |, ||, ?, ??логический (,||)), зависимый от opnd (?, ??)
язык разметки ColdFusion (CFML)нетAND, OR, , ||Boolean
D , |, ||, ?Boolean (,||), зависимо от opnd (?)
Eiffel an d, or, а затем, или ещеBoolean
Erlang и, or, а также, orelseBoolean
Fortran .and., .or..and., .or.Boolean
Go, Haskell, OCaml none, ||Boolean
Java, MATLAB, R, Swift , |, ||Boolean
JavaScript, Julia , |, ||Last value
Lasso noneи, or, , ||Последнее значение
Kotlin и, or, ||Boolean
Lisp, Lua, Scheme noneи, orПоследнее значение
MUMPS (M), !нетЧисловое
Модула-2 нетИ, ORЛогическое
Оберон нет, ORBoolean
OCaml none, ||Boolean
Pascal and, or,and_then, or_else,Boolean
Perl , |, и, ||, orПоследнее значение
Ruby и, or, ||Последнее значение
PHP , |, и, ||, orBoolean
Оболочка POSIX (список команд)нет, ||Last значение (выход)
Python noneи, orПоследнее значение
Rust , |, ||Boolean
Smalltalk , |и:, или:Логическое
Стандартное ML Неизвестнои также, илиЛогическое
TTCN-3 Нети, orЛогическое
Visual Basic.NET И, OrAndAlso, OrElseBoolean
Visual Basic, Visual Basic для приложений (VBA)и, OrВыберите регистрNumeric
Wolfram Language И @@ {...}, Или @@ {...}И, Or, , ||Логическое
ZTT, |нетBoolean

ABAP и APL не имеют отдельного логического типа.. При перегрузке операторы и ||активны и могут возвращать любой тип.. Это применимо только к выражениям, оцениваемым во время выполнения, static, еслии static assert. Выражения в статических инициализаторах или константах манифеста используют активную оценку.. Операторы Fortran не являются ни коротким замыканием, ни стремлением: спецификация языка позволяет компилятору выбрать метод для оптимизации.. ISO / IEC 10206: 1990 Extended Паскаль допускает, но не требует короткого замыкания.. ISO / IEC 10206: 1990 Extended Pascal поддерживает и_ затеми or_else.. Smalltalk использует short- семантика схемы, пока аргумент и:является блоком (например, false и: [Transcript show: 'Wont see me']).. BASIC языки, поддерживающие операторы CASE сделал это с помощью системы условной оценки, а не в виде таблиц переходов, ограниченных фиксированными метками.. 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 или die; # Прервать выполнение, если some_condition ложно some_condition и die; # Прервать выполнение, если some_condition истинно

POSIX shell идиомы:

modprobe -q some_module echo "some_module installed" || echo "some_module not installed"

Эта идиома предполагает, что echoне может дать сбой.

Возможные проблемы

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

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

if (expressionA myfunc (b)) {do_something (); }

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

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

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

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

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

См. также
Ссылки
Последняя правка сделана 2021-06-08 06:37:26
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте