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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to