Аппликативный порядок вычисления (applicative-order evaluation), напротив, сперва происходит «вычисление аргументов, затем вызов процедуры».
В качестве наглядного примера - попробуем реализовать свою собственную функцию and для clojure.
(defn
#^{:test (fn []
(assert (true? (my-and true)))
(assert (false? (my-and true false)))
(assert (true? (my-and true true)))
(assert (false? (my-and true true false)))
(assert (true? (my-and true true true)))
)}
my-and
([x] x)
([x & more] (if (false? x) x (reduce my-and more)))
)
Отлично. Почему же тогда автор clojure решил использовать макросы в реализации функции and ?
В группе языков lisp, как впрочем и во многих других языках, используется аппликативный порядок вычисления (в общем случае, если не используются мощности «синтаксического сахара»).
Разница между my-and и and в том, что my-and использует аппликативный порядок (т.е все аргументы будут вычислены до вызова функции), в то время как and использует несколько иной порядок.
И, поэтому, один из легальных способов изменить порядок вычисления - применение макросов.
В качестве примера используем функцию foo:
user=> (defn foo[x] (do (println "foo") x))
user=> (my-and (foo false) (foo false) (foo true))
foo
foo
foo
false
user=> (and (foo false) (foo false) (foo true))
foo
false
P.S. Строго говоря, and не использует нормальный порядок вычисления, а «псевдонормальный порядок» на один шаг.
1 комментарий:
Правильно я понимаю, что в Clojure по умолчанию аппликативный порядок?
Отправить комментарий