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
:
> (: erlang length (: dict fetch '|to see| my-dict))
1
> (set my-dict
(: dict append '|to see| '"beaches of Santraginus V" my-dict))
#(dict ...
> (: erlang 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).