Pattern matching as a library
Simen Kjaeraas via Digitalmars-d
digitalmars-d at puremagic.com
Sat Mar 12 05:12:56 PST 2016
As I once again bemoaned D's lack of pattern matching yesterday,
I was inspired to create this[0] implementation, that plays to
D's strengths, allows for user-defined matching, and has a fairly
usable syntax. The core usage looks like this:
unittest {
auto a = tuple(1, "foo");
auto b = match(a) (
_!(int, "foo") = (int i) => 1,
_!(_, _) = () => 0
);
assert(b == 1);
}
With the user-defined matching implemented as follows:
struct Tuple(T...) {
// Implementation
// Magic happens here
bool opMatch(Pattern, Args...)(Pattern p, ref Args args) {
foreach (i, e; p.pattern) {
static if (isTypeTuple!e) {
enum n = countTypes!(p.pattern[0..i]);
args[n] = fields[i];
} else static if (!ignore!e) {
if (fields[i] != e) {
return false;
}
}
}
}
}
Or for Algebraic:
struct Algebraic(T...) {
union {
T fields;
}
size_t which;
bool opMatch(Pattern, Type)(Pattern p, ref Type args) if
(staticIndexOf!(Type, T) > -1) {
enum index = staticIndexOf!(Type, T);
if (index == which) {
args = fields[index];
return true;
}
return false;
}
}
The main problem I see is the temporary allocation of function
arguments on line 124 and their assignment in opMatch, but I
currently don't have a better solution.
Also, while I very much dislike using _ for an identifier, I feel
it may be the best alternative here - it conveys the meaning of
'don't care' for the pattern, and doesn't stand out like a sore
thumb before the exclamation mark. Other suggestions are welcome.
The code is available here, and I encourage everyone to play with
it and critique:
[0]:
https://github.com/Biotronic/Collectanea/blob/master/biotronic/pattern.d
More information about the Digitalmars-d
mailing list