[plt-scheme] Hash-tables and call/cc

From: Danny Yoo (dyoo at cs.wpi.edu)
Date: Mon May 7 16:18:58 EDT 2007

On Mon, 7 May 2007, Jens Axel Søgaard wrote:

> (define (hash-table->generator ht)
>   (let ([continue 'start])
>     (lambda ()
>       (case continue
>         [(done)    #f]
>         [(start)   (let/ec return
>                      (hash-table-for-each
>                       ht
>                       (lambda (x v)
>                         (call/cc
>                          (lambda (k)
>                            (set! continue k)
>                            (return x)))))
>                      (set! continue 'done)
>                      #f)]
>         [else      (continue)]))))

Hi Jens,

"return" looks a little funny: I think we need to reset it every time we 
re-enter the continuation.

We also have to make sure to use return on every exit point, including 
when we're "done".  So something like:

(module hash-table-continuations mzscheme
   (define (hash-table->generator ht)
     (let ([continue 'start]
           [return #f])
       (lambda ()
         (let/cc ret
           (set! return ret)
           (case continue
              (return #f)]
               (lambda (x v)
                  (lambda (k)
                    (set! continue k)
                    (return x)))))
              (set! continue 'done)
              (return #f)]
             [else (continue)]))))))v

appears to work better.

As a self-plug, if you use my generator.plt from PLaneT, the code looks 

   (require (planet "generator.ss" ("dyoo" "generator.plt" 2)))

   (define-generator (hash-table->generator-2 ht)
     (hash-table-for-each ht (lambda (x v) (yield x))))

The only difference is that you get an exception when the generator's 
exhausted rather than the default value of #f.

Best of wishes!

Posted on the users mailing list.