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:

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

key :: any
t :: list | %{}
value :: any

Functions

delete(dict, key)

Specs

delete(t, key) :: t

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
drop(dict, keys)

Specs

drop(t, [key]) :: t

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]
equal?(dict1, dict2)

Specs

equal?(t, t) :: boolean

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
fetch(dict, key)

Specs

fetch(t, key) :: value

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
fetch!(dict, key)

Specs

fetch!(t, key) :: value | no_return

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
get(dict, key, default \\ nil)

Specs

get(t, key, value) :: value

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
has_key?(dict, key)

Specs

has_key?(t, key) :: boolean

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
keys(dict)

Specs

keys(t) :: [key]

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]
merge(dict1, dict2, fun \\ fn _k, _v1, v2 -> v2 end)

Specs

merge(t, t, (key, value, value -> value)) :: t

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]
pop(dict, key, default \\ nil)

Specs

pop(t, key, value) :: {value, t}

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]}
put(dict, key, val)

Specs

put(t, key, value) :: t

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
put_new(dict, key, val)

Specs

put_new(t, key, value) :: t

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
size(dict)

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
split(dict, keys)

Specs

split(t, [key]) :: {t, t}

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], []}
take(dict, keys)

Specs

take(t, [key]) :: t

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)
[]
to_list(dict)

Specs

to_list(t) :: list

Returns a list of key-value pairs stored in dict. No particular order is enforced.

update(dict, key, initial, fun)

Specs

update(t, key, value, (value -> value)) :: t

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!(dict, key, fun)

Specs

update!(t, key, (value -> value)) :: t

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
values(dict)

Specs

values(t) :: [value]

Returns a list of all values in dict. The values are not guaranteed to be in any order.

Examples

iex> dict = Enum.into([a: 1, b: 2], dict_impl.new)
iex> Enum.sort(Dict.values(dict))
[1,2]

Callbacks

delete(t, key)

Specs

delete(t, key) :: t
drop(t, arg1)

Specs

drop(t, Enum.t) :: t
equal?(t, t)

Specs

equal?(t, t) :: boolean
fetch(t, key)

Specs

fetch(t, key) :: {:ok, value} | :error
fetch!(t, key)

Specs

fetch!(t, key) :: value | no_return
get(t, key)

Specs

get(t, key) :: value
get(t, key, value)

Specs

get(t, key, value) :: value
has_key?(t, key)

Specs

has_key?(t, key) :: boolean
keys(t)

Specs

keys(t) :: [key]
merge(t, t)

Specs

merge(t, t) :: t
merge(t, t, list)

Specs

merge(t, t, (key, value, value -> value)) :: t
new()

Specs

new :: t
pop(t, key)

Specs

pop(t, key) :: {value, t}
pop(t, key, value)

Specs

pop(t, key, value) :: {value, t}
put(t, key, value)

Specs

put(t, key, value) :: t
put_new(t, key, value)

Specs

put_new(t, key, value) :: t
size(t)

Specs

size(t) :: non_neg_integer
split(t, arg1)

Specs

split(t, Enum.t) :: {t, t}
take(t, arg1)

Specs

take(t, Enum.t) :: t
to_list(t)

Specs

to_list(t) :: list
update(t, key, value, list)

Specs

update(t, key, value, (value -> value)) :: t
update!(t, key, list)

Specs

update!(t, key, (value -> value)) ::
  t |
  no_return
values(t)

Specs

values(t) :: [value]