[racket] generator performance

From: Greg Hendershott (greghendershott at gmail.com)
Date: Tue Sep 18 22:38:24 EDT 2012

On Tue, Sep 18, 2012 at 12:59 PM, John Clements
<clements at brinckerhoff.org> wrote:
> On Sep 18, 2012, at 5:28 AM, Matthew Flatt wrote:
>> Meanwhile, it might be interesting to try implementing a `generator'
>> form that rewrites its body to implement `yield's that are
>> syntactically apparent (after local-expansion), leaving parameter and
>> continuations to handle the general case.
> +1! +1!
> I'm sure this idea flitted through about twenty minds yesterday.
> John

I've re-read this paragraph at intervals today. What could it mean for
"a yield to be syntactically apparent"?

All I can come up with so far is the following rough idea:

;; Here's a simplest-case generator, as a let loop:
(define foo
   (let loop ([i 5])
     (cond [(not (zero? i))
            (yield i)
            (loop (sub1 i))]))))
(foo) ;5
(foo) ;4
(foo) ;3

;; This macro distills the key pieces:
(define-syntax-rule (make-gen id init more? next)
   (let loop ([id init])
     (cond [more?
            (yield id)
            (loop next)]))))
;; Letting you define the same thing like this:
(define foo2 (make-gen i 5 (not (zero? i)) (sub1 i)))
(foo2) ;5
(foo2) ;4
(foo2) ;3

;; Given those same key pieces, the generator could instead be defined
;; as this equivalent simple producer procedure:
(define-syntax-rule (fake-gen id init more? next)
  (let ([id init])
      (lambda ()
        (cond [more?
               (begin0 id
                 (set! id next))]
              [else (void)]))))
;; Which does yield (no pun intended) the same results:
(define foo3 (fake-gen i 5 (not (zero? i)) (sub1 i)))
(foo3) ;5
(foo3) ;4
(foo3) ;3

Is that even in the same ballpark as what flitted through the twenty minds?

Posted on the users mailing list.