Одной из важных вещей, которые следует отметить, является модель оценки. or
короткое замыкание, поэтому: (or true :some random expression that never gets evaluated:)
никогда не оценивает последнее. or
традиционно используется столько же, сколько управляющая структура, как «логическое или».
В традиционной модели (f x y z)
, x, y и z оцениваются, и к ним применяется f.
При использовании (apply f vec)
содержимое вектора не оценивается, оно принимается как есть. Это наиболее четко видно по вектору символов, они не оценивают в этом контексте свои привязки. Однако это скрыто тем фактом, что модель Clojure для создания вектора несколько отличается от других lisps, [a b c d]
дает вектор, который содержит оценки символов a
, b
, c
и d
. В отличие от большинства Лиспов, где #(a b c d)
не оценивает символы, а просто идентичен оценке (vector 'a 'b 'c 'd)
(или фактически (apply vector '(a b c d))
).
Таким образом, даже если бы можно было применять специальные синтаксические формы, его результат имел бы непрозрачную семантику. or
сначала оценивает свой первый аргумент, если он равен true, останавливается и возвращает его, иначе он переходит ко второму и повторяется до последнего. В случае применения, аргументы уже все оценены, должны ли они оцениваться во второй раз? Скорее всего, что приведет к ошибке во время выполнения?
С точки зрения реализации, было бы очень сильно снизить производительность, если бы синтаксис был также «объектом» и потребовал бы гораздо более сложной модели оценки. Поэтому они не разрешаются во время выполнения, а переписываются в примитивы компилятора во время компиляции.
Но именно по этой причине, когда or
используется логически, а не как управляющая структура, мне самому удобно иметь в наличии функции or/f
, and/f
, if/f
и так далее, которые являются истинными процедуры и оценить все свои аргументы и, следовательно, могут быть применены.