forked from elixir-lang/elixir
/
access.ex
61 lines (50 loc) · 1.48 KB
/
access.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import Kernel, except: [access: 2]
defprotocol Access do
@moduledoc """
The Access protocol is the underlying protocol invoked
when the brackets syntax is used. For instance, `foo[bar]`
is translated to `access foo, bar` which, by default,
invokes the `Access.access` protocol.
This protocol is implemented by default for Lists, Maps
and dictionary like types:
iex> keywords = [a: 1, b: 2]
...> keywords[:a]
1
iex> map = %{ a: 1, b: 2 }
...> map[:a]
1
iex> star_ratings = %{ 1.0 => "★", 1.5 => "★☆", 2.0 => "★★" }
...> star_ratings[1.5]
"★☆"
The key access must be implemented using the `===` operator.
This protocol is limited and is implemented only for the
following built-in types: keywords, records and functions.
"""
@doc """
Receives the element being accessed and the access item.
"""
def access(container, key)
end
defimpl Access, for: List do
def access(dict, key)
def access([{ key, value }|_], key), do: value
def access([{ _, _ }|t], key), do: access(t, key)
def access([], _key), do: nil
end
defimpl Access, for: Map do
def access(map, key) do
case :maps.find(key, map) do
{ :ok, value } -> value
:error -> nil
end
end
end
defimpl Access, for: Atom do
def access(nil, _) do
nil
end
def access(atom, _) do
raise "The access protocol can only be invoked for atoms at " <>
"compilation time, tried to invoke it for #{inspect atom}"
end
end