3 ms·
A lot of these are personal preference and borderline traditionalist, and as pointed out by others, the dynamic binding one is in fact not strictly true. One t
by pmjordan 17y ago
A lot of these are personal preference and borderline traditionalist, and as pointed out by others, the dynamic binding one is in fact not strictly true.
One thing that does however bother me about Clojure is the interaction of dynamic binding and lazy evaluation. Allow me to illustrate:
=> (def *test* 0)
#'user/*test*
=> (binding [*test* 2]
(map #(* % *test*) '(1 2 3)))
(0 0 0)
The call to map is lazy, and the returned seq is only evaluated once it hits the 'P' of REPL, which is outside the dynamic binding of test. If you surround the map call with (doall and ), the result is (2 4 6).
This is of course a trivial case, but I've been bitten by this in practice where the binding, lazy sequence and var evaluation were a few call steps apart, and it's always been very unpleasant. Most of the time, it's involved vars which don't have a root binding, so it throws an error, but in other cases it's a lot more serious.
I guess the same problem can be provoked in both Clojure and CL by returning a closure evaluating that var to back outside the dynamic binding, but since you'd be explicitly invoking the closure, it's a lot more obvious what's going to happen than the "magic" that is lazy evaluation.