binding issue

7 views
Skip to first unread message

bgray

unread,
Jul 12, 2009, 12:01:30 AM7/12/09
to Clojure
Is this behavior expected from binding?

user=> (def a nil)
#'user/a
user=> (def b nil)
#'user/b
user=> (binding [a 1 b (+ a 1)] a)
java.lang.NullPointerException (NO_SOURCE_FILE:0)
user=> (binding [a 1 b (+ a 1)] b)
java.lang.NullPointerException (NO_SOURCE_FILE:0)
user=> (let [a 1 b (+ a 1)] a)
1
user=> (let [a 1 b (+ a 1)] b)
2

Thanks,
Brandon

Tom Faulhaber

unread,
Jul 12, 2009, 1:05:45 AM7/12/09
to Clojure
Looking at the clojure docs, it doesn't appear to be defined whether
binding is a parallel (all vars are computed based on the initial
state) or sequential (vars are computed using the new values for vars
used in the same binding vector). A quick test shows that it appears
to be parallel:

(binding [a 1 b a] [a b]) => [1 nil]

Reviewing the implementation in clojure.contrib makes it seem that is
indeed true. It looks like all of the new values for the binding forms
are computed before the pairs are added to a hash that is sent to
pushThreadBindings.

Whether this is the desired behavior is another question entirely.

In any case, the fact that it is not documented seems like a bug,
especially since this behavior is different from let (as you point
out).

Tom

bgray

unread,
Jul 14, 2009, 3:01:39 PM7/14/09
to Clojure
Ok, so *if* this is intended behavior, what have people been doing to
bind variables dependant on other bindings? I can't be the first to
run into this.

Thanks!
Brandon
> > Brandon- Hide quoted text -
>
> - Show quoted text -

Stuart Sierra

unread,
Jul 14, 2009, 5:12:29 PM7/14/09
to Clojure
On Jul 14, 3:01 pm, bgray <graybran...@gmail.com> wrote:
> Ok, so *if* this is intended behavior, what have people been doing to
> bind variables dependant on other bindings?  I can't be the first to
> run into this.

Just nest multiple binding forms:
(binding [a ...]
(binding [b ...]
...))


Not pretty, but it does what you want. Alternately, use "let" to set
up values sequentially, then bind them all at once.

(let [a ..., b ...]
(binding [*a* a, *b* b] ...))

-SS

Meikel Brandmeyer

unread,
Jul 14, 2009, 5:14:05 PM7/14/09
to clo...@googlegroups.com
Hi,

Am 14.07.2009 um 21:01 schrieb bgray:

> Ok, so *if* this is intended behavior, what have people been doing to
> bind variables dependant on other bindings? I can't be the first to
> run into this.

I haven't run into this, but there are two obvious approaches:

(let [new-a (compute n e w a)]
(binding [a new-a
b (inc new-a)]
[a b]))

(binding [a (comput n e w a)]
(binding [b (inc a)]
[a b]))

I'm not sure it's intended, though. Consistency between
the let-like forms and binding would be nice.

Sincerely
Meikel

Jonathan Smith

unread,
Jul 17, 2009, 10:55:16 PM7/17/09
to Clojure
You could also write a binding* macro that expands to multiple nested
binding forms but looks like the regular binding.
Reply all
Reply to author
Forward
0 new messages