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)))))
(defn find-needle [needle haystack]
;loop binds initial values once,
;then binds values from each recursion call
(loop [needle needle
maybe-here haystack
not-here '()]
(let [needle? (first maybe-here)]
;test for return or recur
(if (or (= (str needle?) (str needle))
(empty? maybe-here))
;return results
[needle? maybe-here not-here]
;recur calls loop with new values
(recur needle
(rest maybe-here)
(concat not-here (list (first maybe-here))))))))
user=>(find-needle "|" "hay|stack")
[\| (\| \s \t \a \c \k) (\h \a \y)]
; makes a simple template function that can be used in mustache way: http://mustache.github.com/
(defn template [tpl env]
(loop [tpl tpl
env env]
(cond (empty? env)
tpl
:else
(let [[key value] (first env)]
(recur (try (clojure.string/replace tpl
(re-pattern (str "\\{\\{" (name key) "\\}\\}"))
value)
(catch Exception e tpl))
(rest env))))))
(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.