Hashes
A Hash is a collection of unique keys and their corresponding values in pairs. In Smojo, the word# ( -- # )creates an empty hash on the stack:
# constant my-hash my-hash . {} okHere
constantbinds the hash created by
#to
my-hash. Therefore, we can get the hash directly by
my-hash. The word
#! ( k v # -- )writes a key-value pair into an existing hash. It requires three arguments: key (k), value (v) and the target hash (#):
"year" 2017 my-hash #! my-hash . {year=2017} okBoth the key and value can be anything -- text and integer ( as in the example above ) or XTs. Anything. The word
#@ ( k # -- v )returns a matching value given its key:
"year" my-hash #@ . 2017 okNote that if the key is not on the hash, the result is a special object called
NULL ( -- null ), which can be tested using the word
NULL? ( * -- f ). For example:
"bingo" my-hash #@ null? . true ok "year" my-hash #@ null? . false okYou may test for the presence of a key-value pair on a hash by using the word
#CONTAINS? ( k # -- f ). This word puts
TRUEon the stack if a key exists on the hash and
FALSEotherwise:
"year" my-hash #contains? . true okThe word
#DROP ( k # -- )removes a key-value pair from the hash; It requires two arguments: key and the target hash table:
"year" my-hash #drop my-hash . {} ok
In summary, hashes are a simple data structure in which you can store and retrieve data temporarily (i.e., as long as your program is running.). Here are some other useful words for a hash:
Word | Action |
---|---|
#@ ( k # -- v ) |
Retrieves a value (v) from a hash given the corresponding key (k). |
#! ( k v # -- ) |
Stores a key-value pair (k v) into a hash. |
#CONTAINS? ( k # -- f ) |
Returns TRUE if the key (k) is on the hash and FALSE otherwise. |
#KEYS ( # -- seq ) |
Takes a hash and returns the sequence of all keys. Note that the keys are returned in no particular order. |
#VALUES ( # -- seq ) |
Takes a hash and returns the sequence of all values. Note that the values are returned in no particular order. |
#SORTED ( -- # ) |
This puts a special "sorted" hash on the stack.
The #KEYSof a sorted hash will be sorted in "alphabetical" (or more precisely, lexicographical) order. |
># ( #t #s -- ) |
Copies the contents of the source hash (#s) into the target hash (#t). |
#EMPTY? ( # -- f ) |
Returns TRUEif the hash is empty, FALSEotherwise. |
#SIZE ( # -- n ) |
Returns the number of key-value pairs in the hash. |
Quiz
Question 1
Is is possible to haveNULLas key or associated value in a hash? Prove your answer using a program.
# constant h null "success" h #! \ possible h . \ {null=success}
Question 2
What happens if a key-value pair is overwritten by the same key but with a different value? Prove your answer using a program.
# constant h "HI" "original" h #! h . cr \ {HI=original} "HI" "overwritten" h #! h . cr \ {HI=overwritten}The old value is overwritten by the new value
Question 3
Create a hash called "me" and write your name, age, and gender into the hash. Then try the following words on your hash:
#SIZE \ returns the number of key-value pairs in the hash. #EMPTY? \ returns true if the hash is empty. #CONTAINS? \ returns true if the has contains the given keyContinue with your hash "me", remove all the key-value pairs from hash "me" and then try
#EMPTY?to see if it is empty now.
# constant me "name" "smojo" me #! "age" 22 me #! "gender" "M" me #! me . cr \ {gender=M, name=smojo, age=22} "size?" . me #size . cr \ size? 3 "empty?" . me #empty? . cr \ empty? false "contains name?" . "name" me #contains? . cr \ contains name? true "contains height?" . "height" me #contains? . cr \ contains height? false "name" me #drop "gender" me #drop "age" me #drop me . cr \ {} "empty?" . me #empty? . cr \ empty? true
Question 4*
The words#KEYSand
#VALUESreturn the keys and the values in a hash as a sequence respectively. Write a word
#CLEARwhich removes all the key-value pairs in a hash. Hint: which word can remove key-value pairs from a hash and which word returns the required input for that word?
: #CLEAR ( # -- # ) begin dup dup #keys head swap #drop dup #empty? until ;
Question 5*
Can a hash be used as a value in a hash? When might this be useful? Hint: how would you store the details of each student (name, height, gender) in a class to be retrieved by that student's ID?
\ hashes can be used as both key and value # constant h # constant h1 # constant h2 h1 h2 h #! h . cr \ {{}={}} \ each student info can be stored in a hash \ each hash is retrievable by student ID \ keys: student ID ; values: hashes of student # constant students \ keys: name, height, gender ; values: corresponding values # constant s1 # constant s2 "name" "Ana" s1 #! "height" 160 s1 #! "gender" "F" s1 #! "name" "Dave" s2 #! "height" 180 s2 #! "gender" "M" s2 #! 1155001 s1 students #! 1155002 s2 students #! students . cr \ {1155001={gender=F, name=Ana, height=160}, \ 1155002={gender=M, name=Dave, height=180}}