This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]