Commit | Line | Data |
---|---|---|
03ac148f SK |
1 | %%%---------------------------------------------------------------------------- |
2 | %%% Equivalent to stdlib's orddict, but with a pretty (IMO), uniform interface. | |
3 | %%%---------------------------------------------------------------------------- | |
4 | -module(hope_kv_list). | |
5 | ||
6 | -behavior(hope_dictionary). | |
7 | ||
8 | -export_type( | |
9 | [ t/2 | |
10 | ]). | |
11 | ||
12 | -export( | |
13 | [ empty/0 | |
14 | , get/2 | |
15 | , set/3 | |
16 | , update/3 | |
17 | , iter/2 | |
18 | , map/2 | |
19 | , filter/2 | |
20 | , fold/3 | |
21 | , of_kv_list/1 | |
22 | , to_kv_list/1 | |
23 | ]). | |
24 | ||
25 | ||
26 | -type t(K, V) :: | |
27 | [{K, V}]. | |
28 | ||
29 | ||
30 | %% ============================================================================ | |
31 | %% API | |
32 | %% ============================================================================ | |
33 | ||
34 | -spec empty() -> | |
35 | []. | |
36 | empty() -> | |
37 | []. | |
38 | ||
39 | get(T, K) -> | |
40 | case lists:keyfind(K, 1, T) | |
41 | of false -> none | |
42 | ; {K, V} -> {some, V} | |
43 | end. | |
44 | ||
45 | set(T, K, V) -> | |
46 | lists:keystore(K, 1, T, {K, V}). | |
47 | ||
48 | update(T, K, F) -> | |
49 | V1Opt = get(T, K), | |
50 | V2 = F(V1Opt), | |
37c6e98b | 51 | % TODO: Eliminate the 2nd lookup. |
03ac148f SK |
52 | set(T, K, V2). |
53 | ||
c1672ac4 | 54 | iter(T, F1) -> |
d10156b0 | 55 | F2 = lift_map(F1), |
c1672ac4 | 56 | lists:foreach(F2, T). |
03ac148f | 57 | |
c1672ac4 | 58 | map(T, F1) -> |
d10156b0 SK |
59 | F2 = fun ({K, _}=X) -> {K, apply_map(F1, X)} end, |
60 | lists:map(F2, T). | |
03ac148f | 61 | |
c1672ac4 | 62 | filter(T, F1) -> |
d10156b0 | 63 | F2 = lift_map(F1), |
c1672ac4 | 64 | lists:filter(F2, T). |
03ac148f SK |
65 | |
66 | fold(T, F1, Accumulator) -> | |
67 | F2 = fun ({K, V}, Acc) -> F1(K, V, Acc) end, | |
68 | lists:foldl(F2, T, Accumulator). | |
69 | ||
70 | to_kv_list(T) -> | |
71 | T. | |
72 | ||
73 | of_kv_list(List) -> | |
37c6e98b | 74 | % TODO: Decide if validation is to be done here. Do so if yes. |
03ac148f SK |
75 | List. |
76 | ||
77 | ||
78 | %% ============================================================================ | |
79 | %% Helpers | |
80 | %% ============================================================================ | |
81 | ||
48371999 SK |
82 | -spec lift_map(F) -> |
83 | G | |
84 | when F :: fun(( K, V1 ) -> V2) | |
85 | , G :: fun(({K, V1}) -> V2) | |
86 | . | |
d10156b0 SK |
87 | lift_map(F) -> |
88 | fun (X) -> apply_map(F, X) end. | |
89 | ||
48371999 SK |
90 | -spec apply_map(fun((K, V1) -> V2), {K, V1}) -> |
91 | V2. | |
d10156b0 SK |
92 | apply_map(F, {K, V}) -> |
93 | F(K, V). |