@c =================================================================== @c
@c    serrano/prgm/project/bigloo/manuals/hash.texi                    @c
@c    ------------------------------------------------------------     @c
@c    Author      :  Manuel Serrano                                    @c
@c    Creation    :  Sat Feb 23 07:41:58 2002                          @c
@c    Last change :                                                    @c
@c    Copyright   :  2002 Manuel Serrano                               @c
@c    ------------------------------------------------------------     @c
@c    Hash tables                                                      @c
@c =================================================================== @c

@c ------------------------------------------------------------------- @c
@c    The hash tables                                                  @c
@c ------------------------------------------------------------------- @c
@node Hash Tables, System Programming, Weak Pointers, Standard Library
@section Hash Tables

Bigloo offers hash tables with support for weak pointers. Here are described 
functions which define and use them.

@deffn {bigloo procedure} make-hashtable [bucket-len] [max-bucket-len] [eqtest] [hash] [weak-keys] [weak-data]
@deffnx {bigloo procedure} create-hashtable [:size] [:max-bucket-len] [:eqtest] [:hash] [:weak] [:max-length] [:bucket-expansion] [:persistent #f]
Defines a hash table for which the number of buckets is @var{size}.
The variable @var{max-bucket-len} specify when the table should be
resized. If provided, these two values have to be exact integers greater or
equal to 1. Normally you could ignore @var{size} and @var{max-bucket-len}
arguments and call @code{make-hashtable} with no argument at all. The argument
@var{eqtest} enables the specification of a comparison function. The first
argument of this function is the keys contained in the table. The second
argument is the searched key. By default,
hash tables rely on @code{hashtable-equal?}, which is defined as:

Persistent hashtables are serializable. Non persistent hashtables are
not.

@smalllisp
(define (hashtable-equal? obj1 obj2)
   (or (eq? obj1 obj2)
       (and (string? obj1)
            (string? obj2)
            (string=? obj1 obj2))))
@end smalllisp

The argument @var{hash} specifies an hashing function. It defaults to
@var{get-hashnumber}.  The arguments @var{weak-keys}, @var{weak-data},
and @var{weak-both} specify respectively whether the hash table should
use weak pointers to store the keys and/or the data.  By default a
hash table uses strong pointers for both keys and data.  Each optional
arguments @var{size}, @var{max-bucket-len}, @var{eqtest}, @var{hash},
@var{weak-keys}, and @var{weak-data} can be bound to the Bigloo value
@code{#unspecified} which forces its default.

The argument @var{max-length} specifies a maximum length (in number of
buckets) for this hashtable. It defaults to @code{16384}. If during the
execution, the hashtable tries to expand itself more than
@var{max-length}, an exception is raised. This feature helps debugging
incorrect hashtable uses because excessive expansion is generally the
signs of an incorrect behavior. Excessive expansions, cause the
garbage collector to crash at some point. This debugging feature can
be disabled by specifying a negative max length, in which case, no check
is performed at runtime.

The argument @var{bucket-expansion} controls how @var{max-bucket-len} is
expanded each time the table grows. This is a floating point number that
is a multiplicative coefficient. It defaults to @code{1.2}.

The function @code{create-hashtable} is equivalent to @code{make-hashtable}
but it uses a keyword interface. The keyword argument @code{weak} can either
be @code{none}, @code{data}, or @code{keys}.
@end deffn

@deffn {bigloo procedure} hashtable? obj
Returns @code{#t} if @var{obj} is an hash table, constructed by
@code{make-hashtable}.
@end deffn

@deffn {bigloo procedure} hashtable-weak-keys? table
Returns @code{#t} if @var{table} is a hash table with weakly pointed keys.
@end deffn

@deffn {bigloo procedure} hashtable-weak-data? table
Returns @code{#t} if @var{table} is a hash table with weakly pointed data.
@end deffn

@deffn {bigloo procedure} hashtable-size table
Returns the number of entries contained in @var{table}.
Note that for a weak hash table the size does not guarantee the real size,
since keys and/or data can dissapear before the next call to the hash table.
@end deffn

@deffn {bigloo procedure} hashtable-contains? table key
Returns the boolean @code{#t} if it exists at least one entry whose key 
is @var{key} in @var{table}. If not entry is found @code{#f} is returned.
Note that for a weak hash table, the fact this procedure returns @code{#t} 
does not guarantee that the key (or its associated data) will not dissapear
before the next call to the hash table.
@end deffn

@deffn {bigloo procedure} hashtable-get table key
Returns the entry whose key is @var{key} in @var{table}. If no entry
is found, or if the key and/or value is weakly pointed to and has dissapeard, 
@code{#f} is returned.
@end deffn

@deffn {bigloo procedure} hashtable-put! table key obj
Puts @var{obj} in @var{table} under the key @var{key}. This function 
returns the object bound in the table. If there was an object 
@var{obj-old} already in the table with the same key as @var{obj}, 
this function returns @var{obj-old}; otherwise it returns @var{obj}.
@end deffn

@deffn {bigloo procedure} hashtable-remove! table key
Removes the object associated to @var{key} from @var{table}, 
returning @code{#t} if such object
was bound in table and @code{#f} otherwise.
@end deffn

@deffn {bigloo procedure} hashtable-add! table key update-fun obj init-value
If key is already in table, the new value is calculated by
@code{(update-fun obj current-value)}. Otherwise the @var{table} is extended
by an entry linking key and @code{(update-fun obj init-value)}.
@end deffn

@deffn {deprecated bigloo procedure} hashtable-update! table key update-fun init-value
If key is already in table, the new value is calculated by
@code{(update-fun current-value)}. Otherwise the @var{table} is extended
by an entry linking key and @code{init-value}.
@end deffn

@deffn {bigloo procedure} hashtable->vector table
@deffnx {bigloo procedure} hashtable->list table
Returns the hash table @var{table}'s data as a vector (respectively a list). 
If the hash table is weak, the result will consist only of the data which 
haven't dissapeared yet and whose keys haven't dissapeared either.
@end deffn

@deffn {bigloo procedure} hashtable-key-list table
Returns the list of keys used in the @var{table}.
If the hash table is weak, the result will consist only of the keys which 
haven't dissapeared yet and whose data haven't dissapeared either.
@end deffn

@deffn {bigloo procedure} hashtable-map table fun
Returns a list whose elements are the result of applying @var{fun} to 
each of the keys and elements of @var{table} (no order is specified). In 
consequence, @var{fun} must be a procedure of two arguments. The first 
one is a key and the second one, an associated object.
If the hash table is weak, @var{fun} will only be mapped on sets of key/datum
which haven't dissapeared yet.
@end deffn

@deffn {bigloo procedure} hashtable-for-each table fun
Applies @var{fun} to each of the keys and elements of @var{table} 
(no order is specified). In consequence, @var{fun} must be a procedure
of two arguments. The first one is a key and the second one, an
associated object.
If the hash table is weak, @var{fun} will only be called on sets of key/datum
which haven't dissapeared yet.
@end deffn

@deffn {bigloo procedure} hashtable-filter! table fun
Filter out elements from @var{table} according to predicate @var{fun}.
If the hash table is weak, @var{fun} will only be called on sets of key/datum
which haven't dissapeared yet.
@end deffn

@deffn {bigloo procedure} hashtable-clear! table
Remove all the elements from @var{table}.
@end deffn

Here is an example of hash table.

@smalllisp
(define *table* (make-hashtable))

(hashtable-put! *table* "toto" "tutu")
(hashtable-put! *table* "tata" "titi")
(hashtable-put! *table* "titi" 5)
(hashtable-put! *table* "tutu" 'tutu)
(hashtable-put! *table* 'foo 'foo)

(print (hashtable-get *table* "toto"))
   @print{} "tutu"
(print (hashtable-get *table* 'foo))
   @print{} 'foo
(print (hashtable-get *table* 'bar))
   @print{} #f

(hashtable-for-each *table* (lambda (key obj) (print (cons key obj))))
   @print{} ("toto" . "tutu")
      ("tata" . "titi")
      ("titi" . 5)
      ("tutu" . TUTU)
      (foo . foo)
@end smalllisp

@deffn {bigloo procedure} hashtable-collisions table
Returns a list of collisions for the keys from @var{table}.
A collision is represented by the number of extra steps (comparisons)
needed for a key. The length of the result gives the number of keys with
collisions, and the sum of all list elements is the sum of all extra
steps needed. This function can help to test different hash functions and
other hash table parameters.
@end deffn

@deffn {bigloo procedure} get-hashnumber obj
@deffnx {bigloo procedure} get-hashnumber-persistent obj

Computes a hash number of the value @var{obj}, which can be of any type.
The function @code{get-hashnumber-persistent} returns a hash number
that is persistent accross program executions and execution platforms.
@end deffn

@deffn {bigloo generic} object-hashnumber object
This generic function computes a hash number of the instance @var{object}.

Example:
@smalllisp
(define-method (object-hashnumber pt::point)
   (with-access::point pt (x y)
      (+fx (*fx x 10) y)))
@end smalllisp
@end deffn

@deffn {bigloo procedure} string-hash string [start 0] [len (string-length string)]
Compute a hash value for @var{string}, starting at index @var{start}, ending
at length @var{len}.
@end deffn

