Common Lisp содержит три логических оператора для булевых значений: and, or и not (и, или, не, соответственно). and и or являются управляющими структурами, потому что их аргументы вычисляются в зависимости от условия. Функции not необходимо инвертировать её один аргумент, поэтому она может быть простой функцией.
not возвращает t, если x является nil, иначе возвращает nil. Таким образом она инвертирует аргумент как булево значение.
null то же, что и not, обе функции включены для ясности. По соглашению принято использовать null, когда надо проверить пустой ли список, и not, когда надо инвертировать булево значение.
(and form1 form2 ... ) последовательно слева направо вычисляет формы. Если какая-либо форма formN вычислилась в nil, тогда немедленно возвращается значение nil без выполнения оставшихся форм. Если все формы кроме последней вычисляются в не-nil значение, and возвращает то, что вернула последняя форма. Таким образом, and может использоваться, как для логических операций, где nil обозначает ложь и не-nil значения истину, так и для условных выражений. Например:
Выражение выше выводит Foo!, если n-ый элемент вектора a-simple-vector является символом foo, проверяя при этом вхождения n в границы вектора a-simple-vector. elt не будет вызвано с аргументом n выходящим за границы вектора, так как and гарантирует ленивую проверку аргументов слева направо.
Оператор and отличается тем, что в определённых случаях вычисляет не все аргументы.
Запись предыдущего примера
будет выполнять ту же функцию. Разница в них только стилистическая. Некоторые программисты никогда не используют в форме and выражения с побочными эффектами, предпочитая для этих целей использовать if или when.
Из общего определения можно сделать дедуктивный вывод о том, что (and x) ≡ x. Также (and) выполняется в t, который тождественен этой операции.
Можно определить and в терминах cond таким образом:
Смотрите id и when, которые иногда являются стилистически более удобными, чем and в целях ветвления. Если необходимо проверить истинность предиката для всех элементов списка или вектора (element 0 and element 1 and element 2 and …), можно использовать функцию every.
(or form1 form2 ... ) последовательно выполняет каждую форму слева направо. Если какая-либо непоследняя форма выполняется в что-либо отличное от nil, or немедленно возвращает это не-nil значение без выполнения оставшихся форм. Если все формы кроме последней, вычисляются в nil, or возвращает то, что вернула последняя форма. Таким образом or может быть использована как для логических операций, в который nil обозначает ложь, и не-nil истину, так и для условного выполнения форм.
Оператор or отличается тем, что в определённых случаях вычисляет не все аргументы.
Из общего определения, можно сделать дедуктивный вывод о том, что (or x) ≡ x. Также, (or) выполняется в nil, который тождественен этой операции.
Можно определить or в терминах cond таким образом:
Смотрите id и unless, которые иногда являются стилистически более удобными, чем or в целях ветвления. Если необходимо проверить истинность предиката для всех элементов списка или вектора (element 0 or element 1 or element 2 or …), можно использовать функцию some.