Elixir v1.2.6 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. The implementation should be added to the
module that defines the struct being access. 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.name
is 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
.