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

From: Christophe Poucet (christophe.poucet at gmail.com)
Date: Mon May 7 16:38:19 EDT 2007

Hello Jens,

I am not certian, but I think the problem resides in the fact that you're
capturing the entire escape-path which now includes the 'list' bit.  This
means that you're calling a separate list on each item.  I remember having
similar issues when I wanted to lazify a structure, and I had to jump through
quite a few hoops to do it with continuations.

But, this seems to be a perfect place to use delimited continuations:

(module foo
  (require (lib "control.ss"))

  (define (hash-table->generator ht)
    (let ([*pair*
            (reset
              (hash-table-for-each
                ht
                (lambda (x v)
		;; Return the value and the remaining computation
                  (shift f (cons f v))))
	      ;; Return a final #f
              (shift f #f))])
      (lambda ()
        (if *pair*
          (let ([temp *pair*])
	    ;; The #f is just a bogus parameter, reset continuations
	    ;; require 1 parameter
            (set! *pair* ((car temp) #f))
            (cdr temp)
            )
          #f))))


  (define g (hash-table->generator
              (make-immutable-hash-table
                '(("1" . 1) ("2" . 2) ("3" . 3)))))
  )


Cheers,
Christophe

Jens Axel Søgaard wrote:
> Hi all,
> 
> I'd like to iterate through the keys in a hash-table
> with srfi-42. In order to do that I'd like a function:
> 
>   hash-table->generator : hash-table -> thunk
> 
> which takes a hash-table as input and returns a
> thunk g as output. The first invocation of g
> returns the first element, the second invocation
> returns the seconc, and so on. When there is no
> left, g simply return #f.
> 
> Here is an attempt do just that:
> 
> (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)]))))
> 
> It almost work - but only almost.
> 
> Here is a session in the REPL:
> 
>> (define g (hash-table->generator
>              (make-immutable-hash-table
>               '(("1" . 1) ("2" . 2) ("3" . 3)))))
>> (g)
> "2"
>> (g)
> "3"
>> (g)
> "1"
>> (g)
> #f
> 
> But now the fun begins:
> 
>> (define g (hash-table->generator
>              (make-immutable-hash-table
>               '(("1" . 1) ("2" . 2) ("3" . 3)))))
>> (list (g) (g))
> (#f done)
> 
> I have missed /something/ in hash-table->generator,
> but what?
> 


-- 
christophe poucet
phd. student
nes - mpsoc ltr

phone:+32 16 28 87 20
e-mail: christophe (dot) poucet (at) imec (dot) be
--------------------------------------------------------------------------------
IMEC vzw – Register of Legal Entities Leuven VAT BE 0425.260.668
         – Kapeldreef 75, B-3001 Leuven, Belgium
         – http://www.imec.be
--------------------------------------------------------------------------------


Posted on the users mailing list.