Am Do., 28. Okt. 2021 um 02:49 Uhr schrieb John Cowan <xxxxxx@ccil.org>:


On Tue, Oct 26, 2021 at 3:14 AM Marc Nieper-Wißkirchen <xxxxxx@gmail.com> wrote:

I think the current generator proposal is fine for situations where the eof object is naturally a value that cannot appear, and this means reading and writing of external representations of Scheme objects (that do have such representations).

Among other things.  The eof object is fine for make-{iota,range}-generator and for {string,bytevector}->generator as well.

Right; although #f would have beeen the more convenient choice for these examples.
 
SRFI 121 and SRFI 158 are, however, advertised to be used in much greater generality. But when they are used to code general algorithms for sequences, the then implementation detail of using eof objects won't be hidden and the algorithms will fail on the most general sequence.

As long as that is documented (and I agree it needs an erratum for that), I don't see a problem.

We still don't have a general "glue" protocol. Maybe we don't need one but it was my impression that generators were meant to provide that glue.
 
For code that is supposed to handle general sequences, a protocol where the output of a generator is a SRFI 189 Maybe would help a lot to write clear and less error-prone code.

That's a possibility, yes.
It does, however, will create an object (the Maybe) that is just going to be destructed by the generator's consumer.

Indeed.
Thus, I find a protocol where the generator-like procedure receives two "continuation procedures" much more natural (especially for a language having proper tail calls). Some syntax could abstract over both cases:

Please demonstrate how gmap would be written and how to set up a gmap tree with a set of map and reduce steps.

Untested:

(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"?

The persistent version with the proposed iterator protocol would be:

(define (iterator-map proc . iter*)
  (let f ([iter* iter*])
    (lambda (succeed fail)
      (let g ([old-iter* old-iter*]
              [val* '()]
              [new-iter* '()])
        (if (null? iter*)
            (succeed (apply proc (reverse val*))
                     (f (reverse new-iter*)))
            (let ([iter (car iter*)]
                  [iter* (cdr iter*)])
              (iter
                (lambda (val new-iter)
                  (g iter* (cons val val*) (cons new-iter new-iter*)))
                (lambda ()
                  (fail)))))))))