The OpenD Programming Language

optionalMatch

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

import mir.algebraic;
alias optionalMatch(visitors...) = visitImpl!(naryFun!visitors, Exhaustive.nullable, true)

Return Value

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

Fuses algebraic types on return.

Examples

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));

Meta