On 03/06/2017 03:28 PM, juan.facorro wrote:
> 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]))

The init value of `a` could rely on `x` or `xs`, so those bindings need
to be established before the loop, which is what the outer loop does.
For example checkout `(walk/macroexpand-all '(loop [[x & xs] xs a x]))`.

> 
> Which returns:
> 
> 
> (let*[G__1249xsvec__1250G__1249x(clojure.core/nthvec__12500nil)
> xs(clojure.core/nthnextvec__12501) a3] (loop*[G__1249G__1249a a]
> (let*[vec__1251G__1249x(clojure.core/nthvec__12510nil)
> xs(clojure.core/nthnextvec__12511) aa])))
> 
> 
> 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
> <mailto:clojure+unsubscr...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout.


-- 
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

-- 
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