doc.txt a hash-table with weak keys

_weak-map.ss_: a hash-table with weak keys

Danny Yoo ( /

_weak-map_ provides a hash-table-like structure that holds its keys
weakly.  If the only references to a key are weak ones, the associated
item will be removed from the map.  This behavior is useful for
implementing things like object caches.

As a full-disclosure thing: most of this isn't really my code, as it comes
almost straight out of the mzscheme reference manual, in the section
on Ephemerons:

I've added a few more functions to the API and made WEAK-MAP-GET's
interface more similar to HASH-TABLE-GET.

Quick Example

    > (require (planet "" ("dyoo" "weak-map.plt")))
    > (define m (make-weak-map))
    > (define message "hello")
    > (weak-map-put! m message message)
    > (weak-map-get m message)
    > (weak-map-map m list)
    (("hello" "world"))
    > (weak-map-get m "ice cream")
    weak-map-get: no value found for key ice cream
    > (weak-map-get m "ice cream" #f)
    > (weak-map-get m "ice cream" (lambda () "munchy"))
    > (collect-garbage)
    > (weak-map-map m list)
    (("hello" "hello"))
    > (set! message #f)
    > (collect-garbage)
    > (weak-map-map m list)


   _weak-map_ :      an implementation of weak-maps.
   _string-intern_ : an example use of weak-map to implement interned
                     string tables.

API for

> make-weak-map: ['equal] -> weak-map
Creates a weak-map.  If the 'equal flag is provides, then keys
are compared by equal?.

> weak-map-get: weak-map key [failure-thunk-or-value] -> void
Returns the value in the weak-map that's associated to the key.

If the key cannot be found and failure-thunk-or-value isnt' provided,
then we raise an error.  If failure-thunk-or-value is a procedure, we
apply it with no argument and return its value.  Otherwise, we just
return it.

> weak-map-put!: weak-map key value -> void
Maps the key to the value, overwriting any preexisting value.

> weak-map-for-each: weak-map proc -> void
Applies the procedure to each key-value pair in the weak-map.  proc
should take two arguments, the key and value, respectively.

> weak-map-map: weak-map proc -> (listof any)
Applies the procedure to each key-value pair in the weak-map, and
collects the results as a list.  proc should take two arguments, the
key and value, respectively.

Another Example: _string-intern.ss_

Here's a more substantial example of a weak-map: the following
function implements a _string-intern_:

    (define string-intern
      (let ([sema (make-semaphore 1)]
            [m (make-weak-map 'equal)])
        (lambda (s)
          (semaphore-wait sema)
          (let ([result
                  m s
                  (lambda ()
                    (let ([immutable-s (string->immutable-string s)])
                      (weak-map-put! m immutable-s immutable-s)
            (semaphore-post sema)
Here, we use the 'equal flag to compare keys by equality.

Since this might be useful, _string-intern.ss_ is also included
with this package.

Example with string-intern

    > (require (planet "" ("dyoo" "weak-map.plt")))
    > (eq? (string-intern "hello") (string-intern (string-append "h" "ello")))

API for

> string-intern: string -> immutable-string
Given a string, returns an immutable string.  If two strings that
come out of string-intern are equal?, then they are also guaranteed
to be eq?.