On Thu, Oct 28, 2021 at 10:23 AM Marc Nieper-Wißkirchen <
xxxxxx@gmail.com> wrote:
(define (gmap proc . gen*)
(lambda (succeed fail)
(let f ([gen* gen*]
[val* '()])
(if (null? gen*)
(succeed (apply proc (reverse val*)))
(let ([gen (car gen*)]
[gen* (cdr gen*)])
(gen
(lambda (val)
(f gen* (cons val val*)))
(lambda ()
(fail))))))))
I am not sure what you were up to, though. What do you mean by a "gmap tree with a set of map and reduce steps"?
Thanks. For comparison, here is a version (also untested) of the sample SRFI 158 implementation. I have removed the check for no generators (signals an error) and the optimized path for a single generator, since your code doesn't have either of them.
(define
(gmap
proc . gens)
(lambda ()
(let ((items (map (lambda (x) (x)) gens)))
(if (any eof-object? items) (eof-object) (apply proc items))))))
That is a very considerable difference in complexity.
The two pieces of code are not completely equivalent. The code given by me stops early while your code calls all generators once for each iteration.
Inherently, there is no difference in complexity, I would say. There's a difference in code length. That stems from the fact that you can readily use `map' and `any' while the equivalent things for the other protocol would have to be actually written down in a library for such a protocol.
In fact, `map' plus `any' is exactly `gmap' for the "callback protocol" so the observation about the different code lengths shouldn't come as a surprise.
Obviously no one is likely to rewrite gmap, but since generators are just procedures, people may wish to write greduce or other novel generator operators.
Provide a few convenience procedures (or syntax) and it wouldn't be any harder.
Let's consider gcombine, for example, which can uses `gmap' as a primitive:
(define (gcombine proc seed . gen*)
(let ((g (apply gmap values gen*))
(lambda (succeed fail)
(g (lambda val*
(let-values (((val new-seed) (apply proc (append val* (list seed)))))
(set! seed new-seed)
val))
fail))))
(Untested code.)
By a gmap tree I meant an expression like (gmap proc0 (gmap proc1 gen1 gen2) (proc2 gen3 gen4)). But that was the wrong question, so never mind.
The persistent version with the proposed iterator protocol would be:
Which is even more complex.
If you mean by complex that it is harder to write, then no. Writing down the code was very natural.
If you want to write one or more SRFIs for imperative and/or functional iterators, I'd be happy to put them on an R7RS docket.
Thanks, but I currently have no capacity for such a thing. :-/