3 Lists and Simple Data
3.4 Property Lists and Hashes
3.4.1 Property Lists
Property lists are just lists whose entries are key/value tuples.
Alternatively, an entry may be a single atom, in which case it implies a tuple
with the atom as the key and true
as the value.
Since there's no special type here, we just create a regular list:
> (set plist
(list
(tuple '|to see|
"moons of Jaglan Beta"
"beaches of Santraginus V")
(tuple '|to avoid|
"small piece of fairy cake")))
>
Let's see what keys we have defined:
> (proplists:get_keys plist)
(|to avoid| |to see|)
>
Extracting data by key:
> (proplists:lookup '|to see| plist)
#(|to see| "moons of Jaglan Beta" "beaches of Santraginus V")
> (proplists:lookup '|to avoid| plist)
#(|to avoid| "small piece of fairy cake")
>
If you know that your value is single-valued (e.g., not a list), then you can do this:
> (proplists:get_value '|to avoid| plist)
"small piece of fairy cake"
>
There is more information about property lists on the docs page for them.
3.4.2 Hashes
There is no builtin "dictionary" or "hash" type in Erlang. However, there are some libraries that support data structures like these. There is also a concept of "records" which we will discuss in another section.
3.4.2.1 The Dictionary
The Erlang dict
module implements a key/value dictionary part of which is
an additional dict
data type which supplements the built-in Erlang data
types.
Here's how you create a new dict
:
> (set my-dict (dict:new))
#(dict
0
16
16
8
80
48
#(() () () () () () () () () () () () () () () ())
#(#(() () () () () () () () () () () () () () () ())))
>
Let's check that there's no actual data in it:
> (dict:size my-dict)
0
Now let's add some!
> (set my-dict
(dict:append '|to see| "moons of Jaglan Beta" my-dict))
#(dict ...
> (set my-dict
(dict:append '|to avoid| "small piece of fairy cake" my-dict))
#(dict ...
>
As you might guess from the usage, dict
s are not updated in-place. A new
dictionary is returned with each call to append
. As such, we need to
reset
with each append.
Is everything there?
> (dict:size my-dict)
2
>
Looking good so far... Now let's get some data out:
> (dict:fetch '|to avoid| my-dict)
("small piece of fairy cake")
>
Why the is the function called "append"? Well, dict
accepts multiple
values for keys. Let's try this out, and then re-query our dict
:
> (length (dict:fetch '|to see| my-dict))
1
> (set my-dict
(dict:append '|to see| "beaches of Santraginus V" my-dict))
#(dict ...
> (length (dict:fetch '|to see| my-dict))
2
> (dict:size my-dict)
2
> (dict:fetch '|to see| my-dict)
("moons of Jaglan Beta" "beaches of Santraginus V")
>
The size of the my-dict
didn't change because we didn't add a new key;
rather, we updated an existing one, appending a new value. The |to see|
key now has two values in it.
You can also build dict
s from a list of tuples:
> (set my-dict-2
(dict:from_list '(#('key1 "foo") #('key2 "bar"))))
#(dict ...
> (dict:size my-dict-2)
2
>
There are many more functions to explore in the dict docs.
3.4.2.2 Other Hash Tables
OTP comes with the ets
module which provides the ability to store very
large quantities of data in an Erlang runtime system. The ets
module
supports hash tables of the following types:
* set
* ordered_set
* bag
* duplicate_bag
The documentation for this module is here, though we will be adding information on how to use this from LFE at a later point (likely a dedicated tutorial).