Hi,

Am 27.06.2009 um 02:23 schrieb _hrrld:

Am I doing something silly? Or perhaps I've misunderstood lazy-seq's
operation.

I think, it's the latter. Here my try on an explanation:

lazy-seq returns a value, which implements ISeq, ie. the seq interface.
The code inside the lazy-seq is used to produce the actual seq. However
it's execution is deferred. Only when you call first or rest/next on the
lazy-seq, the code will be executed.

So we get the first two rules:
1. lazy-seq should be outer-most.
2. The code inside a lazy-seq must return a concrete seq.

For you example this means:

(defn produce
  [pred generator value]
  (lazy-seq
    (when (pred value)
      (let [v (generator value)]
        (cons v (produce pred generator v))))))

What happens?

lazy-seq returns a lazy seq %) which, when realised, return the
cons of the generated value and another lazy-seq of the same type.
As soon as the predicate returns falls, the block inside the lazy-seq
returns nil and the sequence stops.

Then there is a third important rule:
3. Don't hold onto the head.

This is not applicable to your example, but it's good to know.

And finally you can get something similar with Clojure sequence
library. I think it's slightly different to your code, but maybe
it also works for you.

(defn slightly-different-produce
  [pred generator value]
  (take-while pred (iterate generator value)))

Hope this helps.

Sincerely
Meikel


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

Reply via email to