autoMatch

Behaves as match but doesn't enforce at compile time that all types can be handled by the visiting functions.

alias autoMatch(visitors...) = visitImpl!(naryFun!visitors, Exhaustive.auto_, true)

Return Value

optionally nullable type, null value is used if naryFun!visitors can't be called with provided arguments.

Fuses algebraic types on return.

Examples

1 struct Asteroid { uint size; }
2 struct Spaceship { uint size; }
3 alias SpaceObject = Variant!(Asteroid, Spaceship);
4 
5 alias collideWith = autoMatch!(
6     (Asteroid x, Asteroid y) => "a/a",
7     // No visitor for A/S pair 
8     // (Asteroid x, Spaceship y) => "a/s",
9     (Spaceship x, Asteroid y) => "s/a",
10     (Spaceship x, Spaceship y) => "s/s",
11 );
12 
13 import mir.utility: min;
14 // Direct access of a member in case of all algebraic types has this member
15 alias oops = (a, b) => (a.size + b.size) > 3 && min(a.size, b.size) > 1;
16 
17 import mir.conv: to;
18 alias collide = (x, y) => oops(x, y) ? "big-boom".to!(typeof(collideWith(x, y))) : collideWith(x, y);
19 
20 auto ea = Asteroid(1);
21 auto es = Spaceship(2);
22 auto oa = SpaceObject(ea);
23 auto os = SpaceObject(es);
24 
25 // Asteroid-Asteroid
26 assert(collide(ea, ea) == "a/a");
27 assert(collide(ea, oa) == "a/a");
28 assert(collide(oa, ea) == "a/a");
29 assert(collide(oa, oa) == "a/a");
30 
31 // Asteroid-Spaceship
32 // assert(collide(ea, es).isNull);  // Compiler error: incompatible types
33 assert(collideWith(ea, es).isNull); // OK
34 assert(collide(ea, os).isNull);
35 assert(collide(oa, es).isNull);
36 assert(collide(oa, os).isNull);
37 
38 // Spaceship-Asteroid
39 assert(collide(es, ea) == "s/a");
40 assert(collide(es, oa) == "s/a");
41 assert(collide(os, ea) == "s/a");
42 assert(collide(os, oa) == "s/a");
43 
44 // Spaceship-Spaceship
45 assert(collide(es, es) == "big-boom");
46 assert(collide(es, os) == "big-boom");
47 assert(collide(os, es) == "big-boom");
48 assert(collide(os, os) == "big-boom");
49 
50 // check types  
51 
52 static assert(!__traits(compiles, collide(Asteroid.init, Spaceship.init)));
53 static assert(is(typeof(collideWith(Asteroid.init, Spaceship.init)) == Nullable!()));
54 
55 static assert(is(typeof(collide(Asteroid.init, Asteroid.init)) == string));
56 static assert(is(typeof(collide(SpaceObject.init, Asteroid.init)) == string));
57 static assert(is(typeof(collide(Spaceship.init, Asteroid.init)) == string));
58 static assert(is(typeof(collide(Spaceship.init, SpaceObject.init)) == string));
59 static assert(is(typeof(collide(Spaceship.init, Spaceship.init)) == string));
60 
61 static assert(is(typeof(collide(Asteroid.init, SpaceObject.init)) == Nullable!string));
62 static assert(is(typeof(collide(SpaceObject.init, SpaceObject.init)) == Nullable!string));
63 static assert(is(typeof(collide(SpaceObject.init, Spaceship.init)) == Nullable!string));

Meta