This repository has been archived by the owner on Feb 28, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
accessors.ex
111 lines (91 loc) · 2.65 KB
/
accessors.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
defprotocol Nested.Accessors do
@only [Record, Tuple, List, Map]
def put(structure, field, value)
def get(structure, field)
def update(structure, field, func)
end
defimpl Nested.Accessors, for: [HashDict, Map] do
def put(dict, key, value) do
Dict.put(dict, key, value)
end
def get(dict, key) do
Dict.get(dict,key)
end
def update(dict, key, func) do
Dict.update!(dict, key, func)
end
end
defimpl Nested.Accessors, for: Tuple do
#for :dicts
def put(dict, key, value)
when is_record(dict) and elem(dict, 0) == :dict do
:dict.store(key, value, dict)
end
# for Records
def put(record, attribute, value) when is_record(record) do
module = elem(record,0)
apply(module, attribute, [value, record])
end
# for arbitrary tuples
def put(tuple, index, value) when is_integer(index) do
set_elem(tuple, index, value)
end
# for :dicts
def get(dict, key)
when is_record(dict) and elem(dict, 0) == :dict do
:dict.fetch(key, dict)
end
# for Records
def get(record, attribute) when is_record(record) do
module = elem(record,0)
apply(module, attribute, [record])
end
# for arbitrary tuples
def get(tuple, index) when is_integer(index) do
elem(tuple,index)
end
#for :dicts
def update(dict, key, func)
when is_record(dict) and elem(dict, 0) == :dict do
:dict.update(key, func, dict)
end
# for Records
def update(record, accessor, func) when is_record(record) do
module = elem(record,0)
update_acc = list_to_atom('update_' ++ atom_to_list(accessor))
apply(module, update_acc, [func, record])
end
# for arbitrary tuples
def update(tuple, index, func) when is_integer(index) do
old_value = get(tuple, index)
set_elem(tuple, index, func.(old_value))
end
end
defimpl Nested.Accessors, for: List do
# for Keywords or orddict
def put(words, key, value) when is_atom(key) do
Keyword.put(words, key, value)
end
#for index addressed lists - replace respecting position
def put(list, index, value) when is_integer(index) do
{first, second} = Enum.split(list, index)
first ++ [value] ++ Enum.drop(second, 1)
end
# for Keywords or orddict
def get(words, key) when is_atom(key) do
Keyword.get(words,key)
end
#for index addressed lists
def get(list, index) when is_integer(index) do
Enum.fetch!(list, index)
end
# for Keywords or orddict
def update(words, key, func) when is_atom(key) do
Keyword.update!(words, key, func)
end
#for index addressed lists - replace respecting position
def update(list, index, func) when is_integer(index) do
new_value = func.(get(list, index))
put(list, index, new_value)
end
end