macro | since v0.0-927 | clojure.core/loop | Edit |
(loop bindings & body)
Evaluates the body-exprs
in a lexical context in which the symbols in
the binding-forms are bound to their respective init-exprs, just like a let
form.
Acts as a recur
target, which will allow tail-call optimization.
(loop [x 0]
(when (< x 10)
(println x)
(recur (+ x 2))))
;; Prints:
;; 0
;; 2
;; 4
;; 6
;; 8
;;
;;=> nil
Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein. Acts as a recur target.
(core/defmacro loop
[bindings & body]
(assert-args loop
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
(core/let [db (destructure bindings)]
(if (= db bindings)
`(loop* ~bindings ~@body)
(core/let [vs (take-nth 2 (drop 1 bindings))
bs (take-nth 2 bindings)
gs (map (core/fn [b] (if (core/symbol? b) b (gensym))) bs)
bfs (reduce (core/fn [ret [b v g]]
(if (core/symbol? b)
(conj ret g v)
(conj ret g v b g)))
[] (map core/vector bs vs gs))]
`(let ~bfs
(loop* ~(vec (interleave gs gs))
(let ~(vec (interleave bs gs))
~@body)))))))