Well ... in BeyondJS lazy lists are objects that wrap a generator function. The generator functions take a state and return a value and a state, which is used in the next invocation. The wrapper exposes the value through a generalized collection API (the same API is supported by Array objects for example). Thus (2).lazy() returns an object that represents the list of numbers 2..
The lazy list object implement an extend() method that takes another lazy list as an argument and appends it to the original. Internally it creates a new generator that uses the original two generators. Since the generators are just functions, they can be recursive so that the list provided as an argument to extend can be dependent on the original list, as in this case.
Actually it's a little bit more complex. Note that I'm not calling sieve() when passing it as an argument to extend(). Instead I use sieve.using(). This returns a function this when called, invokes sieve() with that argument (thing of it as a function for whom all the arguments have been curried but the function hasn't been called yet - a freeze-dried function). This is really how you do lazy evaluation in JavaScript: instead of passing the result of a calculation pass a reference to a function that performs the calculation.
I've written this off-the-cuff so I hope it's clear.
|