factor/library/collections/hashtables.facts

192 lines
12 KiB
Plaintext
Raw Normal View History

IN: hashtables
USING: hashtables-internals help inspector prettyprint ;
GLOSSARY: "hashtable"
"An instance of the " { $link hashtable } " class, implementing a mutable mapping from keys to values with expected constant lookup time" ;
ARTICLE: "hashtables-internals" "Hashtable implementation details"
"This hashtable implementation uses only one auxilliary array in addition to the hashtable tuple itself. The array stores keys in even slots and values in odd slots. Values are looked up with a hashing strategy that uses linear probing to resolve collisions."
{ $terpri }
"There are two special objects: the " { $link ((tombstone)) } " marker and the " { $link ((empty)) } " marker. Neither of these markers can be used as hashtable keys."
{ $terpri }
"The " { $link hash-count } " slot is the number of entries including deleted entries, and " { $link hash-deleted } " is the number of deleted entries." ;
HELP: hash@ "( key array -- i )"
{ $values { "key" "a key" } { "array" "the underlying array of a hashtable" } { "i" "the index to begin hashtable search" } }
{ $description "Computes the index to begin searching from the hashcode of the key. Always outputs an even value since keys are stored at even indices of the underlying array." } ;
HELP: probe "( array i -- array i )"
{ $values { "array" "the underlying array of a hashtable" } { "i" "a search index" } }
{ $description "Outputs the next hashtable search index." } ;
HELP: key@ "( key hash -- i )"
{ $values { "key" "a key" } { "hash" "a hashtable" } { "i" "the index of the key, or -1 if it is not present" } }
{ $description "Searches the hashtable for the key using a linear probing strategy. Searches stop if either the key or an " { $link ((empty)) } " sentinel is found. Searches skip the " { $link ((tombstone)) } " sentinel." }
{ $see-also new-key@ } ;
HELP: new-key@ "( key hash -- i )"
{ $values { "key" "a key" } { "hash" "a hashtable" } { "i" "the index where the key would be stored" } }
{ $description "Searches the hashtable for the key using a linear probing strategy. If the key is not present in the hashtable, outputs the index where it should be stored." }
{ $see-also new-key@ } ;
HELP: if-key "( key hash true false -- )"
{ $values { "key" "a key" } { "hash" "a hashtable" } { "true" "a quotation to call if the key is found, with stack effect " { $snippet "( true: index key hash -- )" } } { "false" "a quotation to call if the key is not found" } }
{ $description "Searches the hashtable for the key, calling one of the two quotations depending on the outcome." } ;
HELP: nth-pair "( n seq -- key value )"
{ $values { "n" "an index in the sequence" } { "seq" "a sequence" } { "key" "the first element of the pair" } { "value" "the second element of the pair" } }
{ $description "Fetches the elements with index " { $snippet "n" } " and " { $snippet "n+1" } ", respectively." }
{ $safety "This word is in the hashtables-internals vocabulary because it does not perform bounds checks." }
{ $see-also set-nth-pair } ;
HELP: set-nth-pair "( key value n seq -- )"
{ $values { "key" "the first element of the pair" } { "value" "the second element of the pair" } { "n" "an index in the sequence" } { "seq" "a sequence" } }
{ $description "Stores a pair of values into the elements with index " { $snippet "n" } " and " { $snippet "n+1" } ", respectively." }
{ $safety "This word is in the hashtables-internals vocabulary because it does not perform bounds checks." }
{ $see-also nth-pair } ;
HELP: each-pair "( array quot -- )"
{ $values { "array" "an array of pairs" } { "quot" "a quotation with stack effect " { $snippet "( key value -- )" } } }
{ $description "Applies a quotation to successive pairs in the array." }
{ $safety "This word is in the hashtables-internals vocabulary because passing an array of odd length can lead to memory corruption." } ;
HELP: all-pairs? "( array quot -- ? )"
{ $values { "array" "an array of pairs" } { "quot" "a quotation with stack effect " { $snippet "( key value -- ? )" } } { "?" "conjunction of quotation outputs" } }
{ $description "Applies a predicate quotation to successive pairs in the array, and outputs true if the array is empty or if the quotation yields true for each pair." }
{ $safety "This word is in the hashtables-internals vocabulary because passing an array of odd length can lead to memory corruption." } ;
HELP: reset-hash "( n hash -- )"
{ $values { "n" "a positive integer specifying hashtable capacity" } { "hash" "a hashtable" } }
{ $description "Resets the underlying array of the hashtable to a new array with the given capacity. Removes all entries from the hashtable." } ;
HELP: hash-count+ "( hash -- )"
{ $values { "hash" "a hashtable" } }
{ $description "Called to increment the hashtable size when a new entry is added with " { $link set-hash } } ;
HELP: hash-deleted+ "( hash -- )"
{ $values { "hash" "a hashtable" } }
{ $description "Called to increment the deleted entry counter when an entry is removed with " { $link remove-hash } } ;
HELP: hash-deleted- "( hash -- )"
{ $values { "hash" "a hashtable" } }
{ $description "Called to decrement the deleted entry counter when a deleted entry storing the " { $link ((tombstone)) } " sentinel is overwritten with a new entry." } ;
HELP: change-size "( hash old -- )"
{ $values { "hash" "a hashtable" } { "old" "the key about to be overwritten" } }
{ $description "Called to update the hashtable counters when a new entry is added with " { $link set-hash } "." } ;
HELP: (set-hash) "( value key hash -- )"
{ $values { "value" "a value" } { "key" "a key to add" } { "hash" "a hashtable" } }
{ $description "Stores the key/value pair into the hashtable. This word does not grow the hashtable if it exceeds capacity, therefore a hang can result. Client code should use " { $link set-hash } " instead, which grows the hashtable if necessary." } ;
HELP: (set-hash) "( value key hash -- )"
{ $values { "value" "a value" } { "key" "a key to add" } { "hash" "a hashtable" } }
{ $description "Stores the key/value pair into the hashtable. This word does not grow the hashtable if it exceeds capacity, therefore a hang can result. Client code should use " { $link set-hash } " instead, which grows the hashtable if necessary." } ;
HELP: grow-hash "( hash -- )"
{ $values { "hash" "a hashtable" } }
{ $description "Enlarges the capacity of a hashtable. Client code does not need to call this word directly." }
{ $see-also (set-hash) ?grow-hash set-hash } ;
HELP: ?grow-hash "( hash -- )"
{ $values { "hash" "a hashtable" } }
{ $description "Enlarges the capacity of a hashtable if it is almost full. Client code does not need to call this word directly." }
{ $see-also (set-hash) grow-hash set-hash } ;
HELP: hash>seq "( i hash -- seq )"
{ $values { "i" "0 or 1" } { "hash" "a hashtable" } { "seq" "a sequence of keys or values" } }
{ $description "Client code should not call this word. It is unsafe and only used in the implementation of " { $link hash-keys } " and " { $link hash-values } ", both of which are safe." }
{ $safety "This word is in the hashtables-internals vocabulary because passing an invalid value for " { $snippet "i" } " can lead to memory corruption." } ;
HELP: <hashtable> "( n -- hash )"
{ $values { "n" "a positive integer specifying hashtable capacity" } { "hash" "a new hashtable" } }
{ $description "Create a new hashtable capable of storing " { $parameter "n" } " key/value pairs before growing." }
{ $see-also clear-hash hash-size hash-empty? } ;
HELP: associate "( value key -- hash )"
{ $values { "value" "a value" } { "key" "a key" } }
{ $description "Create a new hashtable holding one key/value pair." } ;
HELP: clear-hash "( hash -- )"
{ $values { "hash" "a hashtable" } }
{ $description "Removes all entries from the hashtable." }
{ $see-also remove-hash } ;
HELP: hash-size "( hash -- n )"
{ $values { "hash" "a hashtable" } { "n" "a non-negative integer" } }
{ $description "Outputs the number of entries stored in the hashtable." } ;
HELP: hash-empty? "( hash -- ? )"
{ $values { "hash" "a hashtable" } { "?" "a boolean" } }
{ $description "Tests if the hashtable does not contain any entries." } ;
HELP: hash* "( key hash -- value ? )"
{ $values { "key" "an object to look up in the hashtable" } { "hash" "a hashtable" } { "value" "the value associated to the key, or " { $link f } " if the key is not present in the hashtable" } { "?" "a boolean indicating if the key was present" } }
{ $description "Looks up the value associated with a key. Keys are tested for equality. The boolean flag can decide between the case of a missing value, and a value of " { $link f } "." }
{ $see-also hash-member? hash ?hash ?hash* } ;
HELP: hash-member? "( key hashtable -- ? )"
{ $values { "key" "an object to look up in the hashtable" } { "hash" "a hashtable" } }
{ $description "Tests if the hashtable contains a key/value pair whose key is equal to the given key." }
{ $see-also hash hash* ?hash ?hash* } ;
HELP: ?hash* "( key hashtable/f -- ? )"
{ $values { "key" "an object to look up in the hashtable" } { "hash/f" "a hashtable or " { $link f } } }
{ $description "A variant of " { $link hash* } " overloaded to return " { $link f } " if the given mapping is " { $link f } "." }
{ $see-also hash-member? hash hash* ?hash } ;
HELP: hash "( key hash -- value )"
{ $values { "key" "an object to look up in the hashtable" } { "hash" "a hashtable" } { "value" "the value associated to the key, or " { $link f } " if the key is not present in the hashtable" } }
{ $description "Looks up the value associated with a key. Keys are tested for equality. No distinction is made between a missing value and a value set to " { $link f } "." }
{ $see-also hash-member? hash* ?hash ?hash* } ;
HELP: ?hash "( key hash/f -- ? )"
{ $values { "key" "an object to look up in the hashtable" } { "hash/f" "a hashtable or " { $link f } } { "value" "the value associated to the key, or " { $link f } " if the key is not present in the hashtable" } }
{ $description "A variant of " { $link hash } " overloaded to return " { $link f } " if the given mapping is " { $link f } "." }
{ $see-also hash-member? hash hash* hash ?hash* } ;
HELP: remove-hash "( key hash -- )"
{ $values { "key" "a key" } { "hash" "a hashtable" } }
{ $description "Removes an entry from the hashtable." }
{ $see-also clear-hash } ;
HELP: set-hash "( key hash -- )"
{ $values { "key" "a key" } { "hash" "a hashtable" } }
{ $description "Stores an entry into the hashtable." }
{ $see-also hash remove-hash } ;
HELP: hash-keys "( hash -- keys )"
{ $values { "hash" "a hashtable" } { "keys" "an array of keys" } }
{ $description "Outputs an array of all keys in the hashtable." }
{ $see-also hash-values hash>alist alist>hash } ;
HELP: hash-values "( hash -- keys )"
{ $values { "hash" "a hashtable" } { "values" "an array of values" } }
{ $description "Outputs an array of all values in the hashtable." }
{ $see-also hash-keys hash>alist alist>hash } ;
HELP: hash>alist "( hash -- alist )"
{ $values { "hash" "a hashtable" } { "alist" "an array of key/value pairs" } }
{ $description "Outputs an array of all key/value pairs in the hashtable. Each pair is itself a two-element array." }
{ $see-also hash-keys hash-values alist>hash } ;
HELP: alist>hash "( alist -- hash )"
{ $values { "alist" "a sequence of key/value pairs" } { "hash" "a hashtable" } }
{ $description "Constructs a hashtable from a sequence of key/value pairs, where each pair is a two-element sequence. In the case of duplicate keys, later pairs take precedence." }
{ $see-also hash-keys hash-values hash>alist } ;
HELP: hash-each "( hash quot -- )"
{ $values { "hash" "a hashtable" } { "quot" "a quotation with stack effect " { $snippet "( key value -- )" } } }
{ $description "Applies a quotation to each key/value pair in the hashtable." }
{ $see-also hash-each-with hash-all? hash-all-with? hash-subset hash-subset-with } ;
HELP: hash-all? "( hash quot -- ? )"
{ $values { "hash" "a hashtable" } { "quot" "a quotation with stack effect " { $snippet "( key value -- ? )" } } { "?" "a boolean" } }
{ $description "Applies a predicate quotation to each key/value pair in the hashtable. Outputs true if the hashtable is empty or the quotation yields true for each entry." }
{ $see-also hash-each hash-each-with hash-all-with? hash-subset hash-subset-with } ;
HELP: hash-subset "( hash quot -- subhash )"
{ $values { "hash" "a hashtable" } { "quot" "a quotation with stack effect " { $snippet "( key value -- ? )" } } { "subhash" "a new hashtable" } }
{ $description "Constructs a hashtable consisting of all key/value pairs for which the predicate quotation yields true." }
{ $see-also hash-each hash-each-with hash-all? hash-all-with? hash-subset-with } ;