Elixir v1.2.2 Access behaviour
Key-based access to data structures via the foo[bar] syntax.
Elixir provides two syntaxes for accessing values. user[:name]
is used by dynamic structures, like maps and keywords, while
user.name is used by structs. The main difference is that
user[:name] won’t raise if the key :name is missing but
user.name will raise if there is no :name key.
Key-based lookups
Out of the box, Access works with Keyword and Map:
iex> keywords = [a: 1, b: 2]
iex> keywords[:a]
1
iex> map = %{a: 1, b: 2}
iex> map[:a]
1
iex> star_ratings = %{1.0 => "★", 1.5 => "★☆", 2.0 => "★★"}
iex> star_ratings[1.5]
"★☆"
Access can be combined with Kernel.put_in/3 to put a value
in a given key:
iex> map = %{a: 1, b: 2}
iex> put_in map[:a], 3
%{a: 3, b: 2}
This syntax is very convenient as it can be nested arbitrarily:
iex> users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
iex> put_in users["john"][:age], 28
%{"john" => %{age: 28}, "meg" => %{age: 23}}
Furthermore, Access transparently ignores nil values:
iex> keywords = [a: 1, b: 2]
iex> keywords[:c][:unknown]
nil
Since Access is a behaviour, it can be implemented to key-value
data structures. Access requires the key comparison to be
implemented using the === operator.
Field-based lookups
The Access syntax (foo[bar]) cannot be used to access fields in
structs. That’s by design, as Access is meant to be used for
dynamic key-value structures, like maps and keywords, and not
by static ones like structs.
However Elixir already provides a field-based lookup for structs.
Imagine a struct named User with name and age fields. The
following would raise:
user = %User{name: "john"}
user[:name]
** (UndefinedFunctionError) undefined function User.fetch/2
(User does not implement the Access behaviour)
Structs instead use the user.name syntax:
user.name
#=> "john"
The same user.name syntax can also be used by Kernel.put_in/2
to for updating structs fields:
put_in user.name, "mary"
%User{name: "mary"}
Differently from user[:name], user.name cannot be extended by
the developers, and will be always restricted to only maps and
structs.
Summing up:
user[:name]is used by dynamic structures, is extensible and does not raise on missing keysuser.nameis used by static structures, it is not extensible and it will raise on missing keys
Summary
Functions
Fetches the container’s value for the given key
Gets the container’s value for the given key
Gets and updates the container’s value for the given key, in a single pass
Types
Functions
Fetches the container’s value for the given key.
Gets the container’s value for the given key.
Gets and updates the container’s value for the given key, in a single pass.
The argument function fun must receive the value for the given key (or
nil if the key doesn’t exist in container). It must return a tuple
containing the get value and the new value to be stored in the container.
This function returns a two-element tuple.
The first element is the get value, as returned by fun.
The second element is the container, updated with the value returned by fun.