В большинстве случаев, когда вы хотите это, есть более идиоматический способ сделать это, но просто упражнение, можно отложить оценку на счет. Создавайте выражения и передавайте их логическим операторам, которые при необходимости оценивают последовательность, используя стандарт и / или:
(defn &&* [& fns]
(cond (= 1 (count fns)) ((first fns))
:otherwise
(and ((first fns)) (apply &&* (next fns)))))
(defn ||* [& fns]
(cond (= 1 (count fns)) ((first fns))
:otherwise
(or ((first fns)) (apply ||* (next fns)))))
Example use:
(map
(partial apply &&*)
(map (partial map constantly) ;; thunk all of these values
[["yes" "no"]
[false true]
[true "something"]
[true "something" "false"]]))
("no" false "something" "false")
Другой пример:
(defmacro thunks
"convert expressions into thunks to prevent advance evaluation"
[& exprs]
(let [fns# (map (fn [e] `(fn [] ~e)) exprs)]
(cons 'vector fns#)))
(apply ||* (thunks (+ 1 2) false (* 1 5)))
3
(apply &&* (thunks (+ 1 2) false (* 1 5)))
false
(apply &&* (thunks (+ 1 2) (* 1 5)))
5