Elixir v1.0.5 Dict behaviour
This module specifies the Dict API expected to be implemented by different dictionaries. It also provides functions that redirect to the underlying Dict, allowing a developer to work with different Dict implementations using one API.
To create a new dict, use the new
functions defined
by each dict type:
HashDict.new #=> creates an empty HashDict
In the examples below, dict_impl
means a specific
Dict
implementation, for example HashDict
or Map
.
Protocols
Besides implementing the functions in this module, all
dictionaries are required to implement the Access
protocol:
iex> dict = dict_impl.new
iex> dict = Dict.put(dict, :hello, :world)
iex> dict[:hello]
:world
As well as the Enumerable
and Collectable
protocols.
Match
Dictionaries are required to implement all operations
using the match (===
) operator.
Default implementation
Default implementations for some functions in the Dict
module
are provided via use Dict
.
For example:
defmodule MyDict do
use Dict
# implement required functions (see below)
# override default implementations if optimization
# is needed
end
The client module must contain the following functions:
All functions, except reduce/3
, are required by the Dict behaviour.
reduce/3
must be implemtented as per the Enumerable protocol.
Based on these functions, Dict
generates default implementations
for the following functions:
drop/2
equal?/2
fetch!/2
get/2
get/3
has_key?/2
keys/1
merge/2
merge/3
pop/2
pop/3
put_new/3
split/2
take/2
to_list/1
update/4
update!/3
values/1
All of these functions are defined as overridable, so you can provide your own implementation if needed.
Note you can also test your custom module via Dict
’s doctests:
defmodule MyDict do
# ...
end
defmodule MyTests do
use ExUnit.Case
doctest Dict
defp dict_impl, do: MyDict
end
Summary
Functions
Removes the entry stored under the given key
from dict
.
If dict
does not contain key
, returns the dictionary unchanged
Returns a new dict where the given keys
are removed from dict
.
Any non-member keys are ignored
Check if two dicts are equal using ===
Returns {:ok, value}
associated with key
in dict
.
If dict
does not contain key
, returns :error
Returns the value associated with key
in dict
. If dict
does not
contain key
, it raises KeyError
Returns the value associated with key
in dict
. If dict
does not
contain key
, returns default
(or nil
if not provided)
Returns whether the given key
exists in the given dict
Returns a list of all keys in dict
.
The keys are not guaranteed to be in any order
Merges the dict dict2
into dict dict1
Returns the value associated with key
in dict
as
well as the dict
without key
Stores the given value
under key
in dict
.
If dict
already has key
, the stored value is replaced by the new one
Puts the given value
under key
in dict
unless key
already exists
Returns the number of elements in dict
Returns a tuple of two dicts, where the first dict contains only
entries from dict
with keys in keys
, and the second dict
contains only entries from dict
with keys not in keys
Returns a new dict where only the keys in keys
from dict
are included
Returns a list of key-value pairs stored in dict
.
No particular order is enforced
Update a value in dict
by calling fun
on the value to get a new value. If
key
is not present in dict
then initial
will be stored as the first
value
Update a value in dict
by calling fun
on the value to get a new
value. An exception is generated if key
is not present in the dict
Returns a list of all values in dict
.
The values are not guaranteed to be in any order
Types
Functions
Removes the entry stored under the given key
from dict
.
If dict
does not contain key
, returns the dictionary unchanged.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict = Dict.delete(dict, :a)
iex> Dict.get(dict, :a)
nil
iex> dict = Enum.into([b: 2], dict_impl.new)
iex> Dict.delete(dict, :a) == dict
true
Returns a new dict where the given keys
are removed from dict
.
Any non-member keys are ignored.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict = Dict.drop(dict, [:a, :c, :d])
iex> Dict.to_list(dict)
[b: 2]
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict = Dict.drop(dict, [:c, :d])
iex> Dict.to_list(dict) |> Enum.sort
[a: 1, b: 2]
Check if two dicts are equal using ===
.
Notice this function is polymorphic as it compares dicts of any
type. Each dict implementation also provides an equal?
function,
but they can only compare dicts of the same type.
Examples
iex> dict1 = Enum.into([a: 2, b: 3, f: 5, c: 123], dict_impl.new)
iex> dict2 = [a: 2, b: 3, f: 5, c: 123]
iex> Dict.equal?(dict1, dict2)
true
iex> dict1 = Enum.into([a: 2, b: 3, f: 5, c: 123], dict_impl.new)
iex> dict2 = []
iex> Dict.equal?(dict1, dict2)
false
Returns {:ok, value}
associated with key
in dict
.
If dict
does not contain key
, returns :error
.
Examples
iex> dict = Enum.into([a: 1], dict_impl.new)
iex> Dict.fetch(dict, :a)
{:ok, 1}
iex> Dict.fetch(dict, :b)
:error
Returns the value associated with key
in dict
. If dict
does not
contain key
, it raises KeyError
.
Examples
iex> dict = Enum.into([a: 1], dict_impl.new)
iex> Dict.fetch!(dict, :a)
1
Returns the value associated with key
in dict
. If dict
does not
contain key
, returns default
(or nil
if not provided).
Examples
iex> dict = Enum.into([a: 1], dict_impl.new)
iex> Dict.get(dict, :a)
1
iex> Dict.get(dict, :b)
nil
iex> Dict.get(dict, :b, 3)
3
Returns whether the given key
exists in the given dict
.
Examples
iex> dict = Enum.into([a: 1], dict_impl.new)
iex> Dict.has_key?(dict, :a)
true
iex> Dict.has_key?(dict, :b)
false
Returns a list of all keys in dict
.
The keys are not guaranteed to be in any order.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> Enum.sort(Dict.keys(dict))
[:a,:b]
Merges the dict dict2
into dict dict1
.
If one of the dict2
entries already exists in dict1
, the
functions in entries in dict2
have higher precedence unless a
function is given to resolve conflicts.
Notice this function is polymorphic as it merges dicts of any
type. Each dict implementation also provides a merge
function,
but they can only merge dicts of the same type.
Examples
iex> dict1 = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict2 = Enum.into([a: 3, d: 4], dict_impl.new)
iex> dict = Dict.merge(dict1, dict2)
iex> [a: Dict.get(dict, :a), b: Dict.get(dict, :b), d: Dict.get(dict, :d)]
[a: 3, b: 2, d: 4]
iex> dict1 = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict2 = Enum.into([a: 3, d: 4], dict_impl.new)
iex> dict = Dict.merge(dict1, dict2, fn(_k, v1, v2) ->
...> v1 + v2
...> end)
iex> [a: Dict.get(dict, :a), b: Dict.get(dict, :b), d: Dict.get(dict, :d)]
[a: 4, b: 2, d: 4]
Returns the value associated with key
in dict
as
well as the dict
without key
.
Examples
iex> dict = Enum.into([a: 1], dict_impl.new)
iex> {v, dict} = Dict.pop dict, :a
iex> {v, Enum.sort(dict)}
{1,[]}
iex> dict = Enum.into([a: 1], dict_impl.new)
iex> {v, dict} = Dict.pop dict, :b
iex> {v, Enum.sort(dict)}
{nil,[a: 1]}
iex> dict = Enum.into([a: 1], dict_impl.new)
iex> {v, dict} = Dict.pop dict, :b, 3
iex> {v, Enum.sort(dict)}
{3,[a: 1]}
Stores the given value
under key
in dict
.
If dict
already has key
, the stored value is replaced by the new one.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict = Dict.put(dict, :a, 3)
iex> Dict.get(dict, :a)
3
Puts the given value
under key
in dict
unless key
already exists.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict = Dict.put_new(dict, :a, 3)
iex> Dict.get(dict, :a)
1
Specs
size(t) :: non_neg_integer
Returns the number of elements in dict
.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> Dict.size(dict)
2
Returns a tuple of two dicts, where the first dict contains only
entries from dict
with keys in keys
, and the second dict
contains only entries from dict
with keys not in keys
Any non-member keys are ignored.
Examples
iex> dict = Enum.into([a: 1, b: 2, c: 3, d: 4], dict_impl.new)
iex> {dict1, dict2} = Dict.split(dict, [:a, :c, :e])
iex> {Dict.to_list(dict1) |> Enum.sort, Dict.to_list(dict2) |> Enum.sort}
{[a: 1, c: 3], [b: 2, d: 4]}
iex> dict = Enum.into([], dict_impl.new)
iex> {dict1, dict2} = Dict.split(dict, [:a, :c])
iex> {Dict.to_list(dict1), Dict.to_list(dict2)}
{[], []}
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> {dict1, dict2} = Dict.split(dict, [:a, :b, :c])
iex> {Dict.to_list(dict1) |> Enum.sort, Dict.to_list(dict2)}
{[a: 1, b: 2], []}
Returns a new dict where only the keys in keys
from dict
are included.
Any non-member keys are ignored.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict = Dict.take(dict, [:a, :c, :d])
iex> Dict.to_list(dict)
[a: 1]
iex> dict = Dict.take(dict, [:c, :d])
iex> Dict.to_list(dict)
[]
Specs
to_list(t) :: list
Returns a list of key-value pairs stored in dict
.
No particular order is enforced.
Update a value in dict
by calling fun
on the value to get a new value. If
key
is not present in dict
then initial
will be stored as the first
value.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict = Dict.update(dict, :c, 3, fn(val) -> -val end)
iex> Dict.get(dict, :c)
3
Update a value in dict
by calling fun
on the value to get a new
value. An exception is generated if key
is not present in the dict.
Examples
iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> dict = Dict.update!(dict, :a, fn(val) -> -val end)
iex> Dict.get(dict, :a)
-1