jassinm
jassinm

Reputation: 7491

clojure unsequential let

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

Answers (3)

fogus
fogus

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

Arthur Ulfeldt
Arthur Ulfeldt

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 lets if required.

Upvotes: 2

Kevin
Kevin

Reputation: 25269

I believe binding macro is parallel not sequential.

See: http://clojuredocs.org/clojure_core/clojure.core/binding

Upvotes: 4

Related Questions