[plt-scheme] Hash-tables and call/cc
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
[(done)
(return #f)]
[(start)
(hash-table-for-each
ht
(lambda (x v)
(call/cc
(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
like:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(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!