1 module reggae.ctaa;
2 
3 /**
4 An implementation of an associative array useable at compile-time.
5 Shameless copy of association lists from Lisp.
6  */
7 
8 
9 @safe:
10 
11 
12 struct AssocList(K, V) {
13     import std.algorithm: find;
14     import std.array: empty, front;
15 
16     AssocEntry!(K, V)[] entries;
17 
18     const(V) opIndex(in K key) pure const nothrow {
19         auto res = entries.find!(a => a.key == key);
20         assert(!res.empty, "AssocList does not contain key " ~ key);
21         return res.front.value;
22     }
23 
24     T get(T)(in K key, T defaultValue) pure const {
25         import std.conv: to;
26         auto res = entries.find!(a => a.key == key);
27         return res.empty ? defaultValue : res.front.value.to!T;
28     }
29 
30     const(K)[] keys() pure const nothrow {
31         import std.algorithm: map;
32         import std.array: array;
33         return entries.map!(a => a.key).array;
34     }
35 }
36 
37 struct AssocEntry(K, V) {
38     K key;
39     V value;
40 }
41 
42 
43 AssocEntry!(K, V) assocEntry(K, V)(K key, V value) {
44     return AssocEntry!(K, V)(key, value);
45 }
46 
47 AssocList!(K, V) assocList(K, V)(AssocEntry!(K, V)[] entries = []) {
48     return AssocList!(K, V)(entries);
49 }
50 
51 auto assocListT(T...)(T args) if(T.length % 2 == 0 && T.length > 0) {
52     alias K = T[0];
53     alias V = T[1];
54     AssocEntry!(K, V)[] entries;
55     foreach(i, elt; args) {
56         static if(i % 2 == 0) entries ~= assocEntry(args[i], args[i+1]);
57     }
58     return AssocList!(K, V)(entries);
59 }