This is the mail archive of the
guile@sourceware.cygnus.com
mailing list for the Guile project.
Re: how to work with (weak) hash tables?
Valentin Kamyshenko <val@kamysh.materials.kiev.ua> writes:
> >>>>> "Greg" == Greg Harvey <Greg.Harvey@thezone.net> writes:
>
> Greg> You also missed a simple and obvious way to handle this: set the
> Greg> value of the hash to the value returned by the procedure.
>
>
> Greg> (define (hash-for-each-value! proc hash) (let ((len
> Greg> (vector-length hash))) (do ((i 0 (+ i 1))) ((= i len) ())
> Greg> (for-each (lambda (x) (set-cdr! x (proc (cdr x)))) (vector-ref
> Greg> hash i)))))
> This is exactly a solution that I had in mind. With two minor changes:
> 1. `proc' must be a function of two arguments `(key value)'
> 2. if `proc' returns #unspecified, set-cdr! is not called
> (that is why, I thought about C version of this).
Yeah, I didn't think too much on it; I just finished that big, long
winding mail and went to get a sandwich, took a bite and said 'doh!,
that's so simple' :)
(define (hash-for-each-value! proc hash)
(let ((len (vector-length hash)))
(do ((i 0 (+ i 1)))
((= i len) *unspecified*) ;Better than an empty list
(for-each (lambda (x) (let ((res (proc (car x) (cdr x))))
(if (not (unspecified? res))
(set-cdr! x res))))
(vector-ref hash i)))))
; The good ol' x hash table once again
; set-car! returns unspecified
guile> (hash-for-each-value! (lambda (key val) (if (eq? key 'a)
(set-car! (cons 'a 'b) 'c) (+ val 1))) x)
guile> x
#(((a . 1)) () () () ((b . 2)) () () () () ())
Note, though, that it's now possible to mess up the keys again, if you
have a non-immediate there (this is why I restricted it to only the
value; I did think about that part ;):
guile> (hash-set! x "boo" 1)
1
guile> (hash-for-each-value! (lambda (key val)
(if (eq? key 'a) (set-car! (cons 'a 'b) 'c)
(if (string? key) (string-set! key 0 #\t)
(+ val 1)))) x)
guile> x
#((("too" . 1)) () () () () () () ((a . 1)) ((b . 2)) ())
guile> (hash-ref x "too")
#f
guile> (hashq-ref x "too")
#f
guile> (hashq-ref x "boo")
#f
guile> (hash-ref x "boo")
#f
The only way I can see to really get around this (allowing the key
argument) is to either copy the key that we're passing to the proc
(too much work, too much garbage; we'd be better just doing
hashq-set!), or we need a way to make the key constant (I'm pretty
sure this can't be done in guile currently). It wouldn't help to write
it in c ;)
--
Greg, being really immature, laughed just a bit at scm_sloppy_assx