1 module reggae.ctaa; 2 3 import std.traits; 4 5 /** 6 An implementation of an associative array useable at compile-time. 7 Shameless copy of association lists from Lisp. 8 */ 9 10 11 @safe: 12 13 14 struct AssocList(K, V) { 15 import std.algorithm: find, canFind; 16 import std.array: empty, front; 17 18 AssocEntry!(K, V)[] entries; 19 20 const(V) opIndex(in K key) pure const nothrow { 21 auto res = entries.find!(a => a.key == key); 22 assert(!res.empty, "AssocList does not contain key " ~ key); 23 return res.front.value; 24 } 25 26 void opIndexAssign(V value, K key) { 27 entries ~= AssocEntry!(K, V)(key, value); 28 } 29 30 T get(T)(in K key, T defaultValue) pure const { 31 import std.conv: to; 32 auto res = entries.find!(a => a.key == key); 33 return res.empty ? defaultValue : res.front.value.to!T; 34 } 35 36 const(K)[] keys() pure const nothrow { 37 import std.algorithm: map; 38 import std.array: array; 39 return entries.map!(a => a.key).array; 40 } 41 42 bool opBinaryRight(string op)(in K key) pure const if(op == "in") { 43 return entries.canFind!(a => a.key == key); 44 } 45 46 V[K] toAA() { 47 V[K] ret; 48 foreach(entry; entries) { 49 ret[entry.key] = entry.value; 50 } 51 return ret; 52 } 53 54 string toString() const pure @safe { 55 import std.conv; 56 import std.algorithm; 57 import std.range; 58 return `{` ~ entries.map!(a => text(a.key, ": ", a.value)).join(", ") ~ `}`; 59 } 60 } 61 62 AssocList!(K, V) fromAA(K, V)(V[K] aa) { 63 AssocEntry!(K, V)[] entries; 64 foreach(k, v; aa) entries ~= assocEntry(k, v); 65 return AssocList!(K, V)(entries); 66 } 67 68 struct AssocEntry(K, V) { 69 K key; 70 V value; 71 } 72 73 74 AssocEntry!(K, V) assocEntry(K, V)(K key, V value) { 75 return AssocEntry!(K, V)(key, value); 76 } 77 78 AssocList!(K, V) assocList(K, V)(AssocEntry!(K, V)[] entries = []) { 79 return AssocList!(K, V)(entries); 80 } 81 82 auto assocListT(T...)(T args) if(T.length % 2 == 0 && T.length > 0) { 83 alias K = T[0]; 84 alias V = T[1]; 85 AssocEntry!(K, V)[] entries; 86 foreach(i, elt; args) { 87 static if(i % 2 == 0) entries ~= assocEntry(args[i], args[i+1]); 88 } 89 return AssocList!(K, V)(entries); 90 }