Reputation: 7491
it seem like clojure's let
is sequential and would correspond to a scheme let*
.
Does clojure have an unsequential binding mechanism like scheme's let
?
Upvotes: 5
Views: 199
Reputation: 6236
binding
doesn't give you the same capability as a parallel let
because it depends on the existence of bindings. As mentioned letfn
will work as long as you don't mind wrapping your values in functions. Another solution is to write a parallel let using a macro:
(defmacro letp
[bindings & exprs]
(let [bindings (partition 2 bindings)
vars (->> bindings (map first) vec)
values (->> bindings (map second))]
`((fn ~vars ~@exprs)
~@values)))
So the following holds:
(def a 7)
(letp [a 5 b a] b)
;;=> 7
Upvotes: 1
Reputation: 91554
letfn is a parallel binding form for functions that exists to allow people to write mutually recursive local functions. It's not quite as general as you seek though it can be used in a pinch.
user> (letfn [(a [] 4)
(b [] c)
(c [] a)]
(a))
4
Binding can be used so long as you are assigning values to things in vars and want dynamic scoping
user> (def ^:dynamic x 4)
#'user/x
user> (defn foo [] x)
#'user/foo
user> (binding [x 8] (+ x (foo)))
16 ; the value of x that gets called by foo is modified by the caller
; yielding 16 instead of 12
user> (binding [x 8 a 7] (+ x (foo)))
; Evaluation aborted.
Unable to resolve var: a in this context
if you try to use parallel bindings the dynamic scoping will give different results than let* would in Scheme
user> (def ^:dynamic a 2)
#'user/a
user> (binding [x 8 a 7] (+ x a))
15
user> (binding [x 8 a (+ x 2)] (+ x a))
14 ; this would be 18 if the binding of x to 8 had been used
; instead the root value of 4 was used.
In general It is most common to bind sequentially or use nested let
s if required.
Upvotes: 2
Reputation: 25269
I believe binding
macro is parallel not sequential.
See: http://clojuredocs.org/clojure_core/clojure.core/binding
Upvotes: 4