В программировании охрана — это логическое выражение , которое должно быть оценено как истинное, если выполнение программы должно продолжаться в рассматриваемой ветви. Независимо от того, какой язык программирования используется, охранное предложение , охранный код или охранный оператор — это проверка предварительных условий целостности, используемая для предотвращения ошибок во время выполнения.
Типичным примером является проверка того, что ссылка, которая будет обработана, не является нулевой, что позволяет избежать сбоев из -за нулевого указателя .
Другие варианты использования включают использование логического поля для идемпотентности (поэтому последующие вызовы являются nops ), как в шаблоне dispose .
public String foo ( String username ) { if ( username == null ) { throw new IllegalArgumentException ( "Имя пользователя равно null." ); } // Остальная часть кода метода следует здесь... }
Guard обеспечивает ранний выход из подпрограммы и является широко используемым отклонением от структурного программирования , удаляя один уровень вложенности и приводя к более плоскому коду: [1] замена if guard { ... }
на if not guard: return; ...
.
Использование защитных предложений может быть методом рефакторинга для улучшения кода. В общем, меньшее вложение хорошо, так как это упрощает код и снижает когнитивную нагрузку.
Например, в Python :
# Эта функция не имеет защитного условия def f_noguard ( x ): if isinstance ( x , int ): #код #код #код return x + 1 else : return None# Эквивалентная функция с предложением guard. Обратите внимание, что большая часть кода имеет меньший отступ, что упрощает чтение и рассуждения о def f_guard ( x ): if not isinstance ( x , int ): return None #код #код #код return x + 1
Другой пример, написанный на языке C :
// Эта функция не имеет защитного предложения int funcNoGuard ( int x ) { if ( x >= 0 ) { //код //код //код return x + 1 ; } else { return 0 ; } } // Эквивалентная функция с защитным предложением int funcGuard ( int x ) { if ( x < 0 ) { return 0 ; } //код //код //код return x + 1 ; }
Термин используется с определенным значением в языках программирования APL , Haskell , Clean , Erlang , occam , Promela , OCaml , Swift , [2] Python с версии 3.10 и Scala . [ требуется ссылка ] В Mathematica сторожевые устройства называются ограничениями . Защитные устройства являются фундаментальной концепцией в языке Guarded Command Language , языке формальных методов . Защитные устройства могут использоваться для дополнения сопоставления с образцом возможностью пропускать образец, даже если структура совпадает. Булевы выражения в условных операторах обычно также соответствуют этому определению сторожевого устройства, хотя они называются условиями .
В следующем примере на языке Haskell защитные символы располагаются между каждой парой символов «|» и «=»:
f x | x > 0 = 1 | в противном случае = 0
Это похоже на соответствующую математическую запись:
В этом случае защитные меры находятся в предложениях «если» и «иначе».
Если есть несколько параллельных гардов, они обычно проверяются сверху вниз, и выбирается ветвь первой прошедшей проверку. гарды в списке случаев обычно параллельны.
Однако в Haskell list comprehensions охранники идут последовательно, и если какой-либо из них не срабатывает, элемент списка не создается. Это было бы то же самое, что и объединение отдельных охранников с помощью логического AND , за исключением того, что среди охранников могут быть другие предложения list comprehensions.
Простое условное выражение, уже представленное в CPL в 1963 году, имеет защиту на первом подвыражении и другое подвыражение для использования в случае, если первое не может быть использовано. Некоторые распространенные способы записать это:
(х>0) -> 1/х; 0х>0 ? 1/х : 0
Если второе подвыражение может быть еще одним простым условным выражением, мы можем предоставить больше альтернатив для проверки перед последним провалом :
(x>0) -> 1/x; (x<0) -> -1/x; 0
В 1966 году ISWIM имел форму условного выражения без обязательного fall-through case, тем самым отделяя guard от концепции выбора или-или. В случае ISWIM, если ни одна из альтернатив не могла быть использована, значение должно было быть undefined , что было определено как никогда не вычисляемое в значение.
KRC , «миниатюрная версия» [3] SASL (1976), был одним из первых языков программирования, использовавших термин «guard». Определения его функций могли иметь несколько предложений, и то, которое нужно было применить , выбиралось на основе предложений, которые следовали за каждым предложением:
fac n = 1 , n = 0 = n * fac ( n - 1 ), n > 0
Использование защитных положений и термина «защитное положение» восходит, по крайней мере, к практике Smalltalk 1990-х годов, как это было кодифицировано Кентом Беком . [1]
В 1996 году Dyalog APL принял альтернативный чисто функциональный стиль, в котором охранник является единственной структурой управления. [4] Этот пример на APL вычисляет четность входного числа:
четность ← { 2 ∣ ⍵ : 'нечет' 'чет' }
В дополнение к сторожу, прикрепленному к шаблону, сторож шаблона может относиться к использованию сопоставления шаблона в контексте сторожа. По сути, сопоставление шаблона означает проход. Это значение было введено в предложении для Haskell Саймоном Пейтоном Джонсом под названием «Новый взгляд на сторожа» в апреле 1997 года и использовалось при реализации предложения. Эта функция обеспечивает возможность использования шаблонов в сторожах шаблона.
Пример на расширенном Haskell:
неуклюжая env var1 var2 | Just val1 <- lookup env var1 , Just val2 <- lookup env var2 = val1 + val2 -- ...другие уравнения для неуклюжести...
Это будет выглядеть так: «Неуклюже для среды и двух переменных, в случае если поиск переменных из среды даст значения , это сумма значений. ...» Как и в списочных включениях , защитные элементы расположены последовательно, и если какой-либо из них не срабатывает, ветвь не выполняется.