If I understand Clojure's dynamic vars correctly, in a context where some
var *bar* is already thread-bound, the following code:
(binding [*bar* new-val]
(foo))
is semantically equivalent to:
(let [old-val *bar*]
(set! *bar* new-val)
(try
(foo)
(finally
(set! *bar* old-val))))
The latter version appears to be 3 to 4 times faster if (foo) does nothing.
The binding macro in the first version expands to something like:
(push-thread-bindings (hash-map (var *bar*) new-val))
(try
(foo)
(finally (pop-thread-bindings)))
So the binding macro uses some stack implementation instead of just
remembering the old value on the JVM call stack like the faster version
does. I am probably missing something, but why do dynamic vars need to
have their own stack for bindings?
Also I noticed that replacing "(hash-map (var *bar*) new-val)" with
"{(var *bar*) new-val}" in the above macro expansion makes it about 1.5-2
times faster. This could also be fixed in the source of the binding
defmacro by changing the following line:
(push-thread-bindings (hash-map ~@(var-ize bindings)))
to:
(push-thread-bindings ~(apply hash-map (var-ize bindings)))
--
Mikhail
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en