Hi,

Am 23.05.2009 um 08:43 schrieb Josip Gracin:

I'm getting unexpected behavior trying to use binding and map.  Here's
what happens.

(def *v*)
(defn fun [i] *v*)
(defn bv []
 (binding [*v* 100]
   (map fun [1 2])))

Evaluating (bv) throws "Var *v* is unbound exception".  I expected it
to return (100 100).

Using the released Clojure 1.0.0-

Is this a bug?

No. Map returns a thing which represents the computation
you declared with the call. In this case the thing represents
the sequence of the results of fun applied to the elements
of the vector.

However this computation did not happen, yet, since map
is lazy. That means the computations only happen, when
the actual element of the sequence is accessed. In your
case this probably means when printing at the repl. But
the map "thing" has already left the binding form and the
original binding of *v* (namely none) was restored. Hence
you get the exception.

You have to realise the sequence before letting it out of
your binding. This forces all the computations necessary
to happen. It can be done via the doall function.

(defn bv
  []
  (binding [*v* 100]
    (doall (map fun [1 2]))))

This should fix your problem.

Note, that this is also of relevance for other resources,
eg. files in a with-open form or a database connection.
Here the file is closed when the lazy sequence is realised
and you will run into a similar problem. So when you need
a resource to build your lazy sequence, you have to realise
it at the point it leaves your area of responsibility.

So this is no bug, but expected behaviour.

Sincerely
Meikel

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to