1 module anansi.container.set;
2 
3 import std.algorithm, std.conv, std.range, std.stdio, std.traits;
4 
5 /**
6  * 
7  */
8 struct Set (T) {
9     public this(Stuff)(Stuff stuff) 
10         if (isInputRange!Stuff && 
11             isImplicitlyConvertible!(ElementType!Stuff, T)) {
12         foreach(s; stuff) 
13             insert(s);
14     } 
15 
16     public this(this) {
17         _payload = _payload.dup;
18     }
19 
20     @property size_t length() const {
21         return _payload.length;
22     }
23 
24     /**
25      * Inserts a new value into the set.
26      * Params:
27      *   value = The value to insert into the set.
28      *
29      * Returns:
30      *   Returns true if the value was inserted, or false if the value 
31      *   already existed in the set.
32      */
33     public bool insert(T value) {
34         int n = _payload[value]++;
35         return (n == 0); 
36     }
37 
38     /**
39      * Inserts a range of elements into the set.
40      *
41      * Params:
42      *   stuff = The range of items to insert into the set. 
43      */
44     public void insert(Stuff)(Stuff stuff)
45         if (isInputRange!Stuff && 
46             isImplicitlyConvertible!(ElementType!Stuff, T)) {
47         foreach (s; stuff) 
48             insert(s);
49     }
50 
51     public bool contains(T value) const {
52         auto p = (value in _payload);
53         return (p !is null);
54     }
55 
56     public int opApply(int delegate(ref T) dg) {
57         int rval = 0;
58         auto values = _payload.keys;
59         for(int i = 0; (i < values.length) && (rval != 0); ++i)
60             rval = dg(values[i]);
61         return rval;
62     }
63 
64     private int[T] _payload;
65 }
66 
67 unittest {
68     writeln("Set: Construction from a range.");
69 }
70 
71 unittest {
72     writeln("Set: Unique values are added.");
73     Set!int s;
74     foreach(n; 0 .. 5) {
75         assert (s.insert(n), "Inserting a unique item should return true.");
76     }
77 
78     assert (s.length == 5, "Expected length of 5, got: " ~to!string(s.length));
79     foreach(n; 0 .. 5) {
80         assert (s.contains(n), "Expected value " ~ to!string(n) ~ " missing.");
81     }
82 }
83 
84 unittest {
85     writeln("Set: Duplicate values are not added.");
86     Set!int s;
87     assert (s.insert(1), "Expected insert to return true.");
88     assert (!s.insert(1), "Expected duplicate insert to return false");
89     assert (s.length == 1, "Expected length of 1, got " ~ to!string(s.length));
90 }