For Development HEAD DRAFTSearch (procedure/syntax/module):

Next: , Previous: , Up: Core library   [Contents][Index]

6.14 Dictionaries

A dictionary is a data structure that associates key to value. Gauche provides hashtables (see Hashtables) and treemaps (see Treemaps) as the built-in dictionaries. Some additional libraries provide more dictionary-type data structures.

A generic interface is defined as a dictionary framework (see Dictionary framework), by which you can use dictionaries without knowing its details.

R7RS also defines an abstract dictionary interface as mapping; see R7RS mappings, for the details.


Next: , Previous: , Up: Dictionaries   [Contents][Index]

6.14.1 Hashtables

R7RS-large defines hashtable (scheme.hash-table module, see R7RS hash tables) but its API is not completely consistent with Gauche’s original hashtables and other native APIs.

Rather than mixing different flavor of APIs, we keep Gauche’s native API consistent, and provide R7RS procedures that are inconsistent with aliases—specifically, those procedures are suffixed with -r7 in gauche module. For portable programs, you can import scheme.hash-table to get R7RS names.

Builtin Class: <hash-table>

Hash table class. Inherits <collection> and <dictionary>.

Gauche doesn’t provide immutable hash tables for now. (If you need immutable maps, see Immutable map).

Hash table properties

Function: hash-table? obj

[R7RS hash-table] Returns #t iff obj is a hash table.

Function: hash-table-mutable? ht

[R7RS hash-table] Returns #t iff a hash table ht is mutable. Gauche doesn’t have immutable hash tables, so this procedure always returns #t for any hash tables.

Function: hash-table-comparator ht

Returns a comparator used in the hashtable ht.

Function: hash-table-type ht

This is an old API, superseded by hash-table-comparator.

Returns one of symbols eq?, eqv?, equal?, string=?, general, indicating the type of the hash table ht.

Function: hash-table-num-entries ht
Function: hash-table-size ht

[R7RS hash-table] Return the number of entries in the hash table ht. R7RS name is hash-table-size.

Hash table constructors and converters

Function: make-hash-table :optional comparator

[R7RS+ hash-table] Creates a hash table. The comparator argument specifies key equality and hash function using a comparator (see Basic comparators). If omitted, eq-comparator is used. Note that in R7RS, comparator argument can’t be omitted.

As Gauche’s extension, the comparator argument can also be one of the symbols eq?, eqv?, equal? or string=?. If it is one of those symbols, eq-comparator, eqv-comparator, equal-comparator and string-comparator will be used, respectively.

The comparator must have hash function, of course. See Hashing, for the built-in hash functions. In general, comparators derived from other comparators having hash functions also have appropriate hash functions.

Function: hash-table-from-pairs comparator key&value …

Constructs and returns a hash table from given list of arguments. The comparator argument is the same as of make-hash-table. Each key&value must be a pair, and its car is used as a key and its cdr is used as a value.

Note: This is called hash-table by 0.9.5. R7RS introduced a procedure with the same name, but different interface. We see R7RS version makes more sense, so we’ll eventually switch to it, but the transition will take long time. The R7RS interface is available as hash-table-r7, and we urge you to use it in the new code, and replace existing hash-table with hash-table-from-pairs.

(hash-table-from-pairs 'eq? '(a . 1) '(b . 2))
  ≡
  (rlet1 h (make-hash-table 'eq?)
     (hash-table-put! h 'a 1)
     (hash-table-put! h 'b 2))
Function: hash-table comparator key&value …

An alias of hash-table-from-pairs above. R7RS introduced the same name procedure with different interface (see hash-table-r7 below), and we’d like to switch to it in future. For now, use either hash-table-from-pairs or hash-table-r7, or import scheme.hash-table and write in R7RS.

Function: hash-table-r7 comparator args …

Create and returns a hash table using comparator. The args … are the contents, alternating keys and values.

This is defined as hash-table in R7RS scheme.hash-table (see R7RS hash tables).

(hash-table-r7 'eq? 'a 1 'b 2)
  ≡
  (rlet1 h (make-hash-table 'eq?)
     (hash-table-put! h 'a 1)
     (hash-table-put! h 'b 2))

Note: An R7RS compliant implementation of hash-table may return an immutable hash table. Since Gauche doesn’t have immutable hash tables (we have immutable maps instead; see Immutable map), we return mutable hash tables. However, the portable program should refrain from mutating the returned hash tables.

Function: hash-table-unfold p f g seed comparator :rest args

[R7RS hash-table] Constructs and returns a new hash table with those repetitive steps. Each iteration keeps the current seed value, whose initial value is seed.

  1. Apply a stop predicate p to the current seed value. If it returns a true value, stop.
  2. Apply a value producer f to the current seed value. It must return two values, which are used as a key and the corresponding value, of the hash table.
  3. Apply a next procedure g to the current seed value. The value it returns becomes the next seed value.
Function: hash-table-copy ht :optional mutable?

[R7RS hash-table] Returns a new copy of a hash table ht.

R7RS defines this procedure to return an immutable hash table if the implementation supports one, unless the optional mutable? argument is provided and not false. Gauche doesn’t have immutable hash tables so it ignores the optional argument and always returns a mutable hash table. But when you write a portable programs, keep it in mind.

Function: hash-table-empty-copy ht

[R7RS hash-table] Returns a new mutable empty hash table that has the same properties as the given hash table ht.

Function: alist->hash-table alist :optional comparator

[R7RS+ hash-table] Creates and returns a hash table that has entries of each element in alist, using its car as the key and its cdr as the value. The comparator argument is the same as in make-hash-table. The default value of comparator is eq-comparator.

R7RS doesn’t allow to omit comparator.

Function: hash-table->alist hash-table

[R7RS hash-table]

  (hash-table-map h cons)

Hash table lookup and mutation

Function: hash-table-get ht key :optional default

Search key from a hash table ht, and returns its value if found. If the key is not found in the table and default is given, it is returned. Otherwise an error is signaled.

Function: hash-table-put! ht key value

Puts a key key with a value value to the hash table ht.

Method: ref (ht <hash-table>) key :optional default
Method: (setter ref) (ht <hash-table>) key value

Method versions of hash-table-get and hash-table-put!.

Function: hash-table-ref ht key :optional failure success

[R7RS hash-table] This is R7RS way to look up a hash table.

Look up a value associated to the key in the table ht, then pass it to a procedure success, and returns its value. If success is omitted, an identity function is used.

If there’s no association for key in ht, a thunk failure is called and its result is returned. The default value of failure throws an error.

It is more general than Gauche’s hash-table-get, but if you need to simply return a fallback value in case of failure, you need to wrap it with a clojure, which is annoying. In R7RS, you can use hash-table-ref/default below.

Function: hash-table-ref/default ht key default

[R7RS hash-table] Looks up key in a hash table ht and returns the associated value. If there’s no key in the table, returns default.

This is same as Gauche’s hash-table-get, except that default is not optional. We provide both, for hash-table-get is short and handy.

Function: hash-table-set! ht args …

[R7RS hash-table] This is R7RS version to put associations into a hash table. The args … is a list of alternating keys and values; so, unlike Gauche’s hash-table-put!, you can insert more than one associations at once. It is an error if args … have odd number of arguments.

(hash-table-set! ht 'a 1 'b 2)
  ≡
  (begin (hash-table-put! ht 'a 1)
         (hash-table-put! ht 'b 2))
Function: hash-table-intern!-r7 ht key failure

This is defined in R7RS as hash-table-intern!. We add -r7 suffix to remind that it takes a failure thunk, which is consistent with R7RS hash-table interface but not Gauche’s way.

Lookup key in ht. If there’s already an entry, it just returns the value. Otherwise, it calls a thunk failure, and insert the association of key and the return value of failure into ht, and returns the value.

Function: hash-table-exists? ht key
Function: hash-table-contains? ht key

[R7RS hash-table] Returns #t if a hash table ht has a key key.

R7RS name is hash-table-contains?.

Function: hash-table-delete! ht key

Deletes an entry that has a key key from the hash table ht. Returns #t if the entry has exist, or #f if the entry hasn’t exist. The same function is called hash-table-remove! in STk (except that it returns an undefined value); I use ‘delete’ for consistency to SRFI-1, SRFI-13 and other parts of the libraries.

Note: This is different from R7RS hash-table-delete!, so we provide R7RS interface with an alias hash-table-delete!-r7.

Function: hash-table-delete!-r7 ht key …

Delets entries that have key … from the hash table ht. The key which isn’t in ht has no effect. Returns the number of entries actually deleted.

This is called hash-table-delete! in R7RS, and so as in scheme.hash-table. We provide this under different name, for Gauche’s hash-table-delete! returns a boolean value.

Function: hash-table-clear! ht

[R7RS hash-table] Removes all entries in the hash table ht.

Function: hash-table-push! ht key value

Conses value to the existing value for the key key in the hash table ht and makes it the new value for key. If there’s no entry for key, an entry is created with the value (list value).

Works the same as the following code, except that this function only looks up the key once, thus it’s more efficient.

(hash-table-put! ht key
    (cons value (hash-table-get ht key '())))
Function: hash-table-pop! ht key :optional default

Looks for the value for the key key in the hash table ht. If found and it is a pair, replaces the value for its cdr and returns car of the original value. If no entry for key is in the table, or the value is not a pair, the table is not modified and the procedure returns default if given, or signals an error otherwise.

During the operation the key is looked for only once, thus runs efficiently.

Note: R7RS has hash-table-pop! but its totally different. We provide R7RS version as an alias hash-table-pop!-r7

Function: hash-table-pop!-r7 ht

Removes one arbitrary entry from ht, and returns the removed entry’s key and value as two values. If ht is empty, an error is thrown.

This is called hash-table-pop! in R7RS, and so as in scheme.hash-table.

Function: hash-table-update! ht key proc :optional default

A more general version of hash-table-push! etc. It works basically as the following code piece, except that the lookup of key is only done once.

(let ((tmp (proc (hash-table-get ht key default))))
  (hash-table-put! ht key tmp)
  tmp)

For example, when you use a hash table to count the occurrences of items, the following line is suffice to increment the counter of the item, regardless of whether item has already appeared or not.

(hash-table-update! ht item (cut + 1 <>) 0))

R7RS provides hash-table-update! with different interface, so we provide R7RS version as an alias hash-table-update!-r7.

Function: hash-table-update!-r7 ht key updater :optional failure success

This is R7RS version of hash-table-update!. With no optional arguments, it works like Gauche’s hash-table-update!. But in practice you often needs to specify the behavior when key hasn’t been in ht, in which case R7RS differs from Gauche.

The R7RS version works like this but potentially more efficiently:

(hash-table-put! ht key (updater (hash-table-ref ht key failure success)))
Function: hash-table-update!/default ht key updater default

[R7RS hash-table] This is the same as Gauche’s hash-table-default!, except that the default value can’t be omitted.

Hash table scanners

Function: hash-table-for-each ht proc
Function: hash-table-map ht proc

A procedure proc is called with two arguments, a key and its associated value, over all the entries in the hash table ht.

Function: hash-table-fold ht kons knil

For all entries in the hash table ht, a procedure kons is called with three arguments; a key, its associated value, and the previous return value of kons. The first call of kons receives knil as the third argument. The return value of the last call of kons is returned from hash-table-fold.

Function: hash-table-find ht pred :optional failure

Apply pred with each key and value in the hash table ht. Once pred returns a true value, that return value is immediately returned from hash-table-find. If no key-value satisfies pred, a thunk failure is invoked and its result is returned. If failure is omitted, (lambda () #f) is assumed.

Note: The convention starting from srfi-1 is that *-find returns an item in the collection that satisfy the predicate, while *-any returns a non-false value the predicate returns. SRFI-125 broke the convention. The justification given in SRFI-125 discussion was that the “any” semantics is strictly upper-compatible to the “find” semantics so we can combine two. So far, though, SRFI-125 is the only exception of this convention.

;; Find if hash tables ha and hb has a common key.
(hash-table-find ha (^[k v] (hash-table-exists? hb k)))
Function: hash-table-keys ht
Function: hash-table-values ht

Returns all the keys or values of hash table ht in a list, respectively.

Hash table as sets

Function: hash-table-compare-as-sets ht1 ht2 :optional value=? fallback

A hash table can be viewed as a set of pairs of key and value. This procedure compares two hash tables ht1 and ht2 as such sets.

The key comparators of two tables must match (in terms of equal? of the comparators). Otherwise, an error is signaled.

Two elements of the set are equal to each other iff their keys match with the equality predicate of the key comparator, and their values match with value=? procedure. If omitted, equal? is used for value=?

There can be four cases.

Function: hash-table=? value-cmpr ht1 ht2

[R7RS hash-table] This also compares two hash tables ht1 and ht2 as sets, and returns true iff two are the same. That is, every element in ht1 is also in ht2 and vice versa.

Two element are the same iff their keys are the same in terms of the equality predicate of the tables’ key comparator, and their values are the same in terms of the equality predicate of a comparator value-cmpr.

It is an error if ht1 and ht2 has different key comparators. See also hash-table-compare-as-sets above.

Function: hash-table-union! ht1 ht2
Function: hash-table-intersection! ht1 ht2
Function: hash-table-difference! ht1 ht2
Function: hash-table-xor! ht1 ht2

[R7RS hash-table] Perform set operations on two hashtables ht1 and ht2, and modify ht1 to store the result. Note that these procedures only look at the keys for operation; if the values of the same key differ between ht1 and ht2, the value in ht1 is taken.


Previous: , Up: Dictionaries   [Contents][Index]

6.14.2 Treemaps

Builtin Class: <tree-map>

Tree map class. Tree maps are a data structure that maps key objects to value objects. It’s like hash tables except tree maps uses balanced tree internally. Insertion and lookup is O(log n).

Unlike hashtables, a tree map keeps the order of the keys, so it is easy to traverse entries in the order of keys, to find minimum/maximum keys, or to find a key closest to the given value.

The <tree-map> class inherits <sequence> and <ordered-dictionary>.

Function: make-tree-map :optional comparator
Function: make-tree-map key=? key<?

Creates and returns an instance of <tree-map>. The keys are compared by comparator, whose default is default-comparator. The comparator must have a comparison procedure, for we need a total order in the keys. See Basic comparators, for the details.

For the backward compatibility, make-tree-map also accepts a procedure as a comparator; the procedure must take two keys and returns either -1, 0, or 1, depending on whether the first key is less than, equal to, or greater than the second key, respectively. In other words, it is a comparison procedure of a comparator.

The second form of make-tree-map is also for the backward compatibility; it takes two procedures, each must be a procedure that takes two keys; the first one returns #t iff two keys are equal, and the second one returns #t iff the first key is strictly smaller than the second.

Function: tree-map-comparator tree-map

Returns the comparator used in the tree map.

Function: tree-map-copy tree-map

Copies and returns tree-map. Modification on the returned tree doesn’t affect the original tree.

Function: tree-map-empty? tree-map

Returns #t if tree-map doesn’t have any elements, or #f otherwise.

Function: tree-map-num-entries tree-map

Returns the number of elements in tree-map.

Function: tree-map-exists? tree-map key

Returns #t if tree-map has an entry with key, or #f otherwise.

Function: tree-map-get tree-map key :optional fallback

Looks for key in tree-map. If the entry is found, returns a value corresponding to the key. Otherwise, returns fallback if it is provided, or signals an error.

Function: tree-map-put! tree-map key value

Inserts an entry with a key and corresponding value into tree-map. If there already exists an entry with a key which is equivalent (under key=?), the entry is modified to have value.

Function: tree-map-delete! tree-map key

Deletes an entry with key from tree-map if such an entry exists, and returns #t. If tree-map doesn’t have such an entry, #f is returned.

Function: tree-map-clear! tree-map

Removes all entries in tree-map.

Function: tree-map-update! tree-map key proc :optional fallback

A generalized version of tree-map-push! etc. It works like the following code, except that searching for the key is done only once.

(let ((tmp (proc (tree-map-get tree-map key fallback))))
  (tree-map-put! tree-map key tmp)
  tmp)
Function: tree-map-push! tree-map key value

Looks for an entry with key in tree-map. If it exists, the procedure conses value to the original value and makes it as a new value. Otherwise, the procedure creates a new entry for the key and makes (list value) its value.

Function: tree-map-pop! tree-map key :optional fallback

Looks for an entry with key in tree-map. If it exists and its value is a pair, then the procedure updates its value with cdr of the original value, and returns car of the original entry. If such an entry does not exist, or has a non-pair value, the procedure doesn’t modify tree-map and returns fallback if it is given, otherwise reports an error.

Function: tree-map-min tree-map
Function: tree-map-max tree-map

Returns a pair of a key and its value with the minimum or maximum key, respectively. If tree-map is empty, #f is returned.

Function: tree-map-pop-min! tree-map
Function: tree-map-pop-max! tree-map

Looks for an entry with minimum or maximum key, respectively, then deletes the entry from tree-map and returns a pair of the key and its value of the original entry. If tree-map is empty, #f is returned.

Function: tree-map-fold tree-map proc seed
Function: tree-map-fold-right tree-map proc seed

Iterate over elements in tree-map, applying proc which has a type (key, value, seed) -> seed. The difference of tree-map-fold and tree-map-fold-right is the associative order of applying proc, just like the difference between fold and fold-right.

tree-map-fold:
  (proc Kn Vn (proc Kn-1 Vn-1 ... (proc K0 V0 seed)))

tree-map-fold-right
  (proc K0 V0 (proc K1 V1 ... (proc Kn Vn seed)))

Some examples:

(define tree (alist->tree-map '((3 . a) (7 . b) (5 . c)) = <))

(tree-map-fold tree list* '())
   ⇒ (7 b 5 c 3 a)
(tree-map-fold-right tree list* '())
   ⇒ (3 a 5 c 7 b)
Function: tree-map-map tree-map proc

Calls proc, which must take two arguments, with each key/value pair in tree-map, and collect the results into a list and returns it. The order of results corresponds to the order of keys—that is, the first element of the result list is what proc returns with minimum key and its value, and the last element of the result list is what proc returns with the maximum key and its value. (Note: Like map, the order that proc is actually called is unspecified; proc is better to be side-effect free.)

Function: tree-map-for-each tree-map proc

Calls proc, which must take two arguments, with each key/value pair in tree-map, in the increasing order of the keys. proc is called purely for side effects; the returned values are discarded.

Function: tree-map-floor tree-map probe :optional fallback-key fallback-value
Function: tree-map-ceiling tree-map probe :optional fallback-key fallback-value
Function: tree-map-predecessor tree-map probe :optional fallback-key fallback-value
Function: tree-map-successor tree-map probe :optional fallback-key fallback-value

These procedures search the entry which has the closest key to the given probe. If such an entry is found, returns two values, its key and its value. Otherwise, returns two values, fallback-key and fallback-value, both defaulted to #f.

The criteria of “closest” differ slightly among these procedures; tree-map-floor finds the maximum key which is no greater than probe; tree-map-ceiling finds the minimum key which is no less than probe; tree-map-predecessor finds the maximum key which is strictly less than probe; and tree-map-successor finds the minimum key which is strictly greater than probe.

Function: tree-map-floor-key tree-map probe optional fallback-key
Function: tree-map-ceiling-key tree-map probe optional fallback-key
Function: tree-map-predecessor-key tree-map probe optional fallback-key
Function: tree-map-successor-key tree-map probe optional fallback-key

Like tree-map-floor etc., but only returns the key of the found entry (or fallback-key if there’s no entry which satisfies the criteria).

Function: tree-map-floor-value tree-map probe optional fallback-value
Function: tree-map-ceiling-value tree-map probe optional fallback-value
Function: tree-map-predecessor-value tree-map probe optional fallback-value
Function: tree-map-successor-value tree-map probe optional fallback-value

Like tree-map-floor etc., but only returns the value of the found entry (or fallback-value if there’s no entry which satisfies the criteria).

Function: tree-map->generator/key-range tree-map :key > >= < <= descending

Returns a generator (see Generators) that yields pairs of key and value such that the key is in the specified range. If the descending keyword argument is #f (default), it yields the pairs with increasing keys; otherwise, it yields them with descending keys.

The keyword argument > and >= specifies the lower bound of the key, including and excluding the given key value itself, respectively. If both are given, either one of them is considered.

The keyword argument < and <= specifies the upper bound of the key, including and excluding the given key value itself, respectively. If both are given, either one of them is considered.

(define tm (alist->tree-map '((0 . a) (1 . b) (2 . c) (3 . d) (4 . e))
                            default-comparator))


(use gauche.generator)

(generator->list
  (tree-map->generator/key-range tm :>= 1 :< 4))
  ⇒ ((1 . b) (2 . c) (3 . d))

(generator->list
  (tree-map->generator/key-range tm :>= 1 :< 4 :descending #t))
  ⇒ ((3 . d) (2 . c) (1 . b))

(generator->list
  (tree-map->generator/key-range tm :<= 2))
  ⇒ ((0 . a) (1 . b) (2 . c))

(generator->list
  (tree-map->generator/key-range tm :> 2))
  ⇒ ((3 . d) (4 . e))
Function: tree-map-keys tree-map
Function: tree-map-values tree-map

Returns a list of all keys and all values, respectively. The keys and values are in ascending order of the keys.

Function: tree-map->alist tree-map

Returns a list of pairs of keys and values for all entries. The pairs are in ascending order of the keys.

Function: alist->tree-map alist :optional comparator
Function: alist->tree-map alist key=? key<?

Creates a new tree map with the comparator or key=?/key<? procedures, then populates it with alist, each pair in which are interpreted as a cons of a key and its value. The meaning of comparator, key=? and key<? are the same as make-tree-map.

The following two procedures compares two tree maps with slightly different views.

Function: tree-map-compare-as-sets tree-map1 tree-map2 :optional value=? fallback

Compares two tree maps as sets of entries. If we look at tree maps as sets of entries, we can define a partial order between two maps; they are equal to each other if they have exactly the same entries, and tree-map A is smaller than tree-map B if A us a strict subset of B.

If tree-map1 and tree-map2 are the same, 0 is returned. If tree-map1 is smaller than tree-map2, -1 is returned. If tree-map1 is greater than tree-map2, 1 is returned.

If one argument isn’t subset of the other, we can’t determine the order. In such a case, if fallback is given, it is returned. Otherwise, an error is signalled.

The comparators of tree-map1 and tree-map2 must be the same (equal?), otherwise an error is signalled. See Basic comparators, about the comparators.

An entry is equal to another entry if their keys match in terms of the comparator of the tree-map, and also their values match with the provided value=? predicate, which is defaulted to equal?.

(tree-map-compare-as-sets
 (alist->tree-map '((1 . a) (2 . b) (3 . c)) default-comparator)
 (alist->tree-map '((3 . c) (1 . a) (2 . b)) default-comparator))
 ⇒ 0

(tree-map-compare-as-sets
 (alist->tree-map '((1 . a) (3 . c)) default-comparator)
 (alist->tree-map '((3 . c) (1 . a) (2 . b)) default-comparator))
 ⇒ -1

(tree-map-compare-as-sets
 (alist->tree-map '((1 . a) (3 . c) (4 . d) (2 . b)) default-comparator)
 (alist->tree-map '((3 . c) (1 . a) (2 . b)) default-comparator))
 ⇒ 1

(tree-map-compare-as-sets
 (alist->tree-map '((1 . a) (3 . c) (4 . d)) default-comparator)
 (alist->tree-map '((3 . c) (1 . a) (2 . b)) default-comparator))
 ⇒ ERROR: tree-maps can't be ordered

(tree-map-compare-as-sets
 (alist->tree-map '((1 . a) (3 . c) (4 . d)) default-comparator)
 (alist->tree-map '((3 . c) (1 . a) (2 . b)) default-comparator)
 eq?
 #f)
 ⇒ #f
Function: tree-map-compare-as-sequences tree-map1 tree-map2 :optional value-cmp

Compares two tree maps as sequence of entries, ordered by keys. If both maps have entries with the same key, we use a comparator value-cmp to break the tie (naturally, value-cmp must have ordering predicate.) If value-cmp is omitted, default-comparator is used.

The comparators of tree-map1 and tree-map2 must be the same (equal?), otherwise an error is signalled. See Basic comparators, about the comparators.

If tree-map1 and tree-map2 are the same, 0 is returned. If tree-map1 is smaller than tree-map2, -1 is returned. If tree-map1 is greater than tree-map2, 1 is returned.

Unlike tree-map-compare-as-sets, this procedure defines total order of tree maps which share the same comparator.

(tree-map-compare-as-sequences
 (alist->tree-map '((1 . a) (3 . c)) default-comparator)
 (alist->tree-map '((3 . c) (2 . b)) default-comparator))
 ⇒ -1

(tree-map-compare-as-sequences
 (alist->tree-map '((2 . b) (3 . d)) default-comparator)
 (alist->tree-map '((3 . c) (2 . b)) default-comparator))
 ⇒ 1
 

Previous: , Up: Dictionaries   [Contents][Index]


For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT