meldInto

Takes two structs or classes of the same type and melds them together, making the members a union of the two.

In the case of classes it only overwrites members in intoThis that are typeof(member).init, so only unset members get their values overwritten by the melding class. It also does not work with static members.

In the case of structs it also overwrites members that still have their default values, in cases where such is applicable.

Supply a template parameter MeldingStrategy to decide to which extent values are overwritten.

  1. void meldInto(QualThing meldThis, Thing intoThis)
    void
    meldInto
    (
    QualThing
    Thing
    )
    (
    auto ref QualThing meldThis
    ,
    ref Thing intoThis
    )
    if (
    isAggregateType!Thing &&
    is(QualThing : Thing)
    &&
    isMutable!Thing
    )
  2. void meldInto(Array1 meldThis, Array2 intoThis)
  3. void meldInto(QualAA meldThis, AA intoThis)

Parameters

strategy

To what extent the source object should overwrite set (non-init) values in the receiving object.

meldThis QualThing

Object to meld (source).

intoThis Thing

Reference to object to meld (target).

Examples

struct Foo
{
    string abc;
    int def;
    bool b = true;
}

Foo foo, bar;
foo.abc = "from foo"
foo.b = false;
bar.def = 42;
foo.meldInto(bar);

assert(bar.abc == "from foo");
assert(bar.def == 42);
assert(!bar.b);  // false overwrote default value true
1 import std.conv : to;
2 
3 static struct TestFoo
4 {
5     string abc;
6     string def;
7     int i;
8     float f;
9     double d;
10     int[string] aa;
11     int[] arr;
12     int* ip;
13 
14     void blah() {}
15 
16     const string kek;
17     immutable bool bur;
18 
19     this(bool bur)
20     {
21         kek = "uden lo";
22         this.bur = bur;
23     }
24 }
25 
26 TestFoo f1; // = new TestFoo;
27 f1.abc = "ABC";
28 f1.def = "DEF";
29 f1.aa = [ "abc" : 123, "ghi" : 789 ];
30 f1.arr = [ 1, 0, 3, 0, 5 ];
31 
32 TestFoo f2; // = new TestFoo;
33 f2.abc = "this won't get copied";
34 f2.def = "neither will this";
35 f2.i = 42;
36 f2.f = 3.14f;
37 f2.aa = [ "abc" : 999, "def" : 456 ];
38 f2.arr = [ 0, 2, 0, 4 ];
39 
40 f2.meldInto(f1);
41 
42 with (f1)
43 {
44     import std.math : isNaN;
45 
46     assert((abc == "ABC"), abc);
47     assert((def == "DEF"), def);
48     assert((i == 42), i.to!string);
49     assert((f == 3.14f), f.to!string);
50     assert(d.isNaN, d.to!string);
51     assert((aa == [ "abc" : 123, "def" : 456, "ghi" : 789 ]), aa.to!string);
52     assert((arr == [ 1, 2, 3, 4, 5 ]), arr.to!string);
53 }
54 
55 TestFoo f3; // new TestFoo;
56 f3.abc = "abc";
57 f3.def = "def";
58 f3.i = 100_135;
59 f3.f = 99.9f;
60 f3.aa = [ "abc" : 123, "ghi" : 789 ];
61 f3.arr = [ 1, 0, 3, 0, 5 ];
62 
63 TestFoo f4; // new TestFoo;
64 f4.abc = "OVERWRITTEN";
65 f4.def = "OVERWRITTEN TOO";
66 f4.i = 0;
67 f4.f = 0.1f;
68 f4.d = 99.999;
69 f4.aa = [ "abc" : 999, "def" : 456 ];
70 f4.arr = [ 9, 2, 0, 4 ];
71 
72 f4.meldInto!(MeldingStrategy.aggressive)(f3);
73 
74 with (f3)
75 {
76     static if (__VERSION__ >= 2091)
77     {
78         import std.math : isClose;
79     }
80     else
81     {
82         import std.math : approxEqual;
83         alias isClose = approxEqual;
84     }
85 
86     assert((abc == "OVERWRITTEN"), abc);
87     assert((def == "OVERWRITTEN TOO"), def);
88     assert((i == 100_135), i.to!string); // 0 is int.init
89     assert((f == 0.1f), f.to!string);
90     assert(isClose(d, 99.999), d.to!string);
91     assert((aa == [ "abc" : 999, "def" : 456, "ghi" : 789 ]), aa.to!string);
92     assert((arr == [ 9, 2, 3, 4, 5 ]), arr.to!string);
93 }
94 
95 // Overwriting is just aggressive but always overwrites bools.
96 
97 struct User
98 {
99     enum Class { anyone, blacklist, whitelist, admin }
100     string nickname;
101     string alias_;
102     string ident;
103     string address;
104     string login;
105     bool special;
106     Class class_;
107 }
108 
109 User one;
110 with (one)
111 {
112     nickname = "foobar";
113     ident = "NaN";
114     address = "herpderp.net";
115     special = false;
116     class_ = User.Class.whitelist;
117 }
118 
119 User two;
120 with (two)
121 {
122     nickname = "foobar^";
123     alias_ = "FooBar";
124     address = "asdf.org";
125     login = "kamelusu";
126     special = true;
127     class_ = User.Class.blacklist;
128 }
129 
130 //import lu.conv : Enum;
131 
132 User twoCopy = two;
133 
134 one.meldInto!(MeldingStrategy.conservative)(two);
135 with (two)
136 {
137     assert((nickname == "foobar^"), nickname);
138     assert((alias_ == "FooBar"), alias_);
139     assert((ident == "NaN"), ident);
140     assert((address == "asdf.org"), address);
141     assert((login == "kamelusu"), login);
142     assert(special);
143     assert(class_ == User.Class.whitelist);//, Enum!(User.Class).toString(class_));
144 }
145 
146 one.class_ = User.Class.blacklist;
147 
148 one.meldInto!(MeldingStrategy.overwriting)(twoCopy);
149 with (twoCopy)
150 {
151     assert((nickname == "foobar"), nickname);
152     assert((alias_ == "FooBar"), alias_);
153     assert((ident == "NaN"), ident);
154     assert((address == "herpderp.net"), address);
155     assert((login == "kamelusu"), login);
156     assert(!special);
157     assert(class_ == User.Class.blacklist);//, Enum!(User.Class).toString(class_));
158 }
159 
160 struct EnumThing
161 {
162     enum Enum { unset, one, two, three }
163     Enum enum_;
164 }
165 
166 EnumThing e1;
167 EnumThing e2;
168 e2.enum_ = EnumThing.Enum.three;
169 assert(e1.enum_ == EnumThing.Enum.init);//, Enum!(EnumThing.Enum).toString(e1.enum_));
170 e2.meldInto(e1);
171 assert(e1.enum_ == EnumThing.Enum.three);//, Enum!(EnumThing.Enum).toString(e1.enum_));
172 
173 struct WithArray
174 {
175     string[] arr;
176 }
177 
178 WithArray w1, w2;
179 w1.arr = [ "arr", "matey", "I'ma" ];
180 w2.arr = [ "pirate", "stereotype", "unittest" ];
181 w2.meldInto(w1);
182 assert((w1.arr == [ "arr", "matey", "I'ma", "pirate", "stereotype", "unittest" ]), w1.arr.to!string);
183 
184 WithArray w3, w4;
185 w3.arr = [ "arr", "matey", "I'ma" ];
186 w4.arr = [ "arr", "matey", "I'ma" ];
187 w4.meldInto(w3);
188 assert((w3.arr == [ "arr", "matey", "I'ma" ]), w3.arr.to!string);
189 
190 struct Server
191 {
192     string address;
193 }
194 
195 struct Bot
196 {
197     string nickname;
198     Server server;
199 }
200 
201 Bot b1, b2;
202 b1.nickname = "foobar";
203 b1.server.address = "freenode.net";
204 
205 assert(!b2.nickname.length, b2.nickname);
206 assert(!b2.server.address.length, b2.nickname);
207 b1.meldInto(b2);
208 assert((b2.nickname == "foobar"), b2.nickname);
209 assert((b2.server.address == "freenode.net"), b2.server.address);
210 
211 b2.nickname = "harbl";
212 b2.server.address = "rizon.net";
213 
214 b2.meldInto!(MeldingStrategy.aggressive)(b1);
215 assert((b1.nickname == "harbl"), b1.nickname);
216 assert((b1.server.address == "rizon.net"), b1.server.address);
217 
218 class Class
219 {
220     static int i;
221     string s;
222     bool b;
223 }
224 
225 Class abc = new Class;
226 abc.i = 42;
227 abc.s = "some string";
228 abc.b = true;
229 
230 Class def = new Class;
231 def.s = "other string";
232 abc.meldInto(def);
233 
234 assert((def.i == 42), def.i.to!string);
235 assert((def.s == "other string"), def.s);
236 assert(def.b);
237 
238 abc.meldInto!(MeldingStrategy.aggressive)(def);
239 assert((def.s == "some string"), def.s);
240 
241 struct Bools
242 {
243     bool a = true;
244     bool b = false;
245 }
246 
247 Bools bools1, bools2, inverted, backupInverted;
248 
249 bools2.a = false;
250 
251 inverted.a = false;
252 inverted.b = true;
253 backupInverted = inverted;
254 
255 bools2.meldInto(bools1);
256 assert(!bools1.a);
257 assert(!bools1.b);
258 
259 bools2.meldInto(inverted);
260 assert(!inverted.a);
261 assert(inverted.b);
262 inverted = backupInverted;
263 
264 bools2.meldInto!(MeldingStrategy.overwriting)(inverted);
265 assert(!inverted.a);
266 assert(!inverted.b);
267 inverted = backupInverted;
268 
269 struct Asdf
270 {
271     string nickname = "sadf";
272     string server = "asdf.net";
273 }
274 
275 Asdf a, b;
276 a.server = "a";
277 b.server = "b";
278 b.meldInto!(MeldingStrategy.aggressive)(a);
279 assert((a.server == "b"), a.server);
280 
281 a.server = "a";
282 b.server = Asdf.init.server;
283 b.meldInto!(MeldingStrategy.aggressive)(a);
284 assert((a.server == "a"), a.server);
285 
286 struct Blah
287 {
288     int yes = 42;
289     @Unmeldable int no = 24;
290 }
291 
292 Blah blah1, blah2;
293 blah1.yes = 5;
294 blah1.no = 42;
295 blah1.meldInto!(MeldingStrategy.aggressive)(blah2);
296 assert((blah2.yes == 5), blah2.yes.to!string);
297 assert((blah2.no == 24), blah2.no.to!string);