While I was debugging some code I found something related to the *loop *macro
that I found curious. I'm probably missing something but here it goes.
The expression generated by the *loop* macro includes a wrapping *let *when
there is any de-structuring in the bindings.
(require '[clojure.walk :as walk])
(walk/macroexpand-all '(loop [[x & xs] xs a 3]))
Which returns:
(let* [G__1249 xs
vec__1250 G__1249
x (clojure.core/nth vec__1250 0 nil)
xs (clojure.core/nthnext vec__1250 1)
a 3]
(loop* [G__1249 G__1249 a a]
(let* [vec__1251 G__1249
x (clojure.core/nth vec__1251 0 nil)
xs (clojure.core/nthnext vec__1251 1)
a a])))
Since all bindings get re-defined in the inner *let*, why is the outer *let*
even generated? Is there a reason for not having the following generated
instead?
(loop* [G__1249 xs a a]
(let* [vec__1251 G__1249
x (clojure.core/nth vec__1251 0 nil)
xs (clojure.core/nthnext vec__1251 1)
a a]))
The change in the loop macro is pretty simple and it seems to work (at least
with the tests available in GitHub's clojure/clojure).
(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
(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)]
`(loop* ~(vec (interleave gs vs))
(let ~(vec (interleave bs gs))
~@body))))))
But maybe this hasn't been changed because of the importance of the *loop*
macro, or maybe the impact in compile- and run-time is insignificant to justify
the change.
Anyways... I thought I'd put the question out there.
Cheers!
Juan
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.