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.
;looping is recursive in Clojure, the loop construct is a hack so that something like tail-recursive-optimization works in clojure.
user=> (defn my-re-seq [re string]
"Something like re-seq"
(let [matcher (re-matcher re string)]
(loop [match (re-find matcher) ;loop starts with 2 set arguments
result []]
(if-not match
result
(recur (re-find matcher) ;loop with 2 new arguments
(conj result match))))))
#'user/my-re-seq
user=> (my-re-seq #"\d" "0123456789")
["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"]
;; Read decoded MP3 data in loop (requires mp3plugin.jar on class path)
;; http://java.sun.com/javase/technologies/desktop/media/jmf/mp3/download.html
(import '(javax.sound.sampled AudioSystem AudioFormat$Encoding))
(let [mp3-file (java.io.File. "tryout.mp3")
audio-in (AudioSystem/getAudioInputStream mp3-file)
audio-decoded-in (AudioSystem/getAudioInputStream AudioFormat$Encoding/PCM_SIGNED audio-in)
buffer (make-array Byte/TYPE 1024)]
(loop []
(let [size (.read audio-decoded-in buffer)]
(when (> size 0)
;do something with PCM data
(recur)))))
(defmacro loop
"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."
{:added "1.0", :special-form true, :forms '[(loop [bindings*] exprs*)]}
[bindings & body]
(assert-args loop
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
(let [db (destructure bindings)]
(if (= db bindings)
`(loop* ~bindings ~@body)
(let [vs (take-nth 2 (drop 1 bindings))
bs (take-nth 2 bindings)
gs (map (fn [b] (if (symbol? b) b (gensym))) bs)
bfs (reduce1 (fn [ret [b v g]]
(if (symbol? b)
(conj ret g v)
(conj ret g v b g)))
[] (map vector bs vs gs))]
`(let ~bfs
(loop* ~(vec (interleave gs gs))
(let ~(vec (interleave bs gs))
~@body)))))))
Comments top
No comments for loop. Log in to add a comment.