On Jan 24, 6:29 am, Konrad Hinsen <konrad.hin...@laposte.net> wrote:
> I am trying to generate a var for use in a generator for a stream. As
> a simple example, let's try to create a stream of integers. My first
> attempt at the generator was:
>
> (with-local-vars [n 0]
>    (defn integers [_]
>      (let [current (var-get n)]
>        (var-set n (inc current))
>        current)))
>
> I thought this would create a var n initialized to zero that would be
> captured in the closure. But it doesn't work:
>
> (integers nil)
> java.lang.IllegalStateException: Var null/null is unbound.
> (NO_SOURCE_FILE:0)
>
> Next try: create the local inside the function:
>
> (defn integers [_]
>    (with-local-vars [n 0]
>      (let [current (var-get n)]
>        (var-set n (inc current))
>        current)))
>
> This works but, as I expected, the var is initialized at every call,
> so the generator returns zero forever.
>
> I didn't find any other way to create a local var, so I am a bit at a
> loss. Any ideas?
>

First off, it is very important to understand Vars and thread-local
binding before using with-local-vars:

http://clojure.org/vars

Such local vars only have utility in the dynamic context of the with-
local-vars block, they are unbound otherwise, and closing over them
for use in other than in the same dynamic context won't work. Calling
defn within with-local-vars is certainly not going to do something
useful :)

So, thread-local vars are not what you want.

Second, generators are not supposed to be aliased - you are supposed
to create them on the fly and hand them off for ownership by a stream,
so creating a top-level generator fn (with state!) is also not what
you want. What you want is either a generator constructing fn:

(defn integer-generator []
  (let [n (atom -1)]
    (fn [_]
        (swap! n inc))))

(take 5 (stream (integer-generator)))
-> (0 1 2 3 4)

or a stream constructing fn:

(defn integers []
  (let [n (atom -1)]
    (stream
     (fn [_]
         (swap! n inc)))))

(take 5 (integers))
-> (0 1 2 3 4)

Rich

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to