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/2equal?/2fetch!/2get/2get/3has_key?/2keys/1merge/2merge/3pop/2pop/3put_new/3split/2take/2to_list/1update/4update!/3values/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