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
smime.p7s
Description: S/MIME cryptographic signature
