nullable variant, null value is used if naryFun!visitors can't be called with provided arguments.
Fuses algebraic types on return.
1 static struct Asteroid { uint size; } 2 static struct Spaceship { uint size; } 3 alias SpaceObject = Variant!(Asteroid, Spaceship); 4 5 alias collideWith = optionalMatch!( 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 alias collide = (x, y) => oops(x, y) ? "big-boom".nullable : collideWith(x, y); 18 19 auto ea = Asteroid(1); 20 auto es = Spaceship(2); 21 auto oa = SpaceObject(ea); 22 auto os = SpaceObject(es); 23 24 // Asteroid-Asteroid 25 assert(collide(ea, ea) == "a/a"); 26 assert(collide(ea, oa) == "a/a"); 27 assert(collide(oa, ea) == "a/a"); 28 assert(collide(oa, oa) == "a/a"); 29 30 // Asteroid-Spaceship 31 // assert(collide(ea, es).isNull); // Compiler error: incompatible types 32 assert(collideWith(ea, es).isNull); // OK 33 assert(collide(ea, os).isNull); 34 assert(collide(oa, es).isNull); 35 assert(collide(oa, os).isNull); 36 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)) == Nullable!string)); 56 static assert(is(typeof(collide(Asteroid.init, SpaceObject.init)) == Nullable!string)); 57 static assert(is(typeof(collide(SpaceObject.init, Asteroid.init)) == Nullable!string)); 58 static assert(is(typeof(collide(SpaceObject.init, SpaceObject.init)) == Nullable!string)); 59 static assert(is(typeof(collide(SpaceObject.init, Spaceship.init)) == Nullable!string)); 60 static assert(is(typeof(collide(Spaceship.init, Asteroid.init)) == Nullable!string)); 61 static assert(is(typeof(collide(Spaceship.init, SpaceObject.init)) == Nullable!string)); 62 static assert(is(typeof(collide(Spaceship.init, Spaceship.init)) == Nullable!string));
Behaves as match but doesn't enforce at compile time that all types can be handled by the visiting functions.