<br><br><div class="gmail_quote">On Sun, Apr 4, 2010 at 17:18, Lutger <span dir="ltr"><<a href="mailto:lutger.blijdestijn@gmail.com">lutger.blijdestijn@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div class="im">bearophile wrote:<br>
<br>
> I'm not currently asking to implement pattern matching in D3 (as present<br>
> for example in Scala), but it's positive to think how to solve similar<br>
> problems in D2, because even if pattern matching is not available in D2,<br>
> the problems it is asked to solve solve can be real.<br>
><br>
> Walter or Andrei has recently shown here a possible implementation idea,<br>
> but I don't remember where the post is and what the implementation was. And<br>
> it wasn't a small compilable program.<br>
<br>
</div>It was a subthread under the 'is D a cult' thread, this was the basic<br>
example:<br>
<br>
foo( v,<br>
(int i) { writeln("I saw an int ", i); },<br>
(string s) { writeln("I saw a string ", s); ),<br>
(Variant any) { writeln("I saw the default case ", any); }<br>
);<br><br></blockquote><div><br>I went the other way round and wrote something more compile-time oriented:<br><br>usage:<br><br>match!(fun1, fun2, fun3)(someValues...); // as many values as you wish<br><br>where the funX can be template functions (or anything template-y _and_ callable), to harness the pattern matching inherent in templates, variadic templates, and so on.<br>
<br>For example, given:<br><br>string any(T...)(T t) { return "any: " ~ typeof(t).stringof;}<br><br>T one(T)(T t) { return t;}<br><br>T[] twoEqual(T)(T t1, T t2) { return [t1,t2];}<br><br>Tuple!(T,U) twoDiff(T,U)(T t, U u) { return tuple(t,u);}<br>
<br>string three(T)(T t1, T t2, T t3) { return T.stringof ~ " thrice";}<br><br>you can do:<br><br>alias match!(one, twoEqual, twoDiff, three, any) matcher;<br><br>auto m = matcher(1); // 1<br>auto m = matcher(1,2); // [1,2]<br>
auto m = matcher(1,'a'); // Tuple!(int,char)(1,'a')<br>auto m = matcher(1,2,3,4); // string "any: (int,int,int,int)"<br><br>You can also use standard functions, of course, and mix templates and functions.<br>
I used this to create trees of tuples (tuples of values and tuples) and pattern-match on them. It's far from being as beautiful as Haskell code, but it's enough for my needs.<br><br>One interest compared to function overload is that you can have different return types depending on the function you give it as params.<br>
<br>I have another version that deconstruct the values: if you send it a struct containing two ints and one of your function has two ints as params, it will match. But it's buggy as hell and I sould have a look at it before posting it.<br>
<br>For match, here is the code:<br><br>template match(alias fun, Rest...) {<br> auto match(M...)(M m) { // curried template...<br> return Matcher!(fun, M.length, M, Rest)(m)();<br> }<br>}<br><br>
struct Matcher(alias fun, size_t n, Rest...) {<br>
TypeTuple!(Rest[0..n]) _m;<br>
this(TypeTuple!(Rest[0..n]) m) { _m = m;}<br>
auto opCall() {<br>
static if (is(typeof(fun(_m))))<br>
return fun(_m);<br>
else static if (n == 1 && is(typeof(fun(_m[0])))) // I'm not sure this is necessary<br>
return fun(_m[0]);<br>
else static if (Rest.length > n) {<br>
return Matcher!(Rest[n], n, Rest[0..n], Rest[n+1..$])(_m)();<br>
}<br>
else { // no match found, we are at the end of Rest<br>
string s;<br>
foreach(i, Type; TypeTuple!(Rest[0..n])) s ~=
to!string(_m[i]);<br>
throw new NoMatchException("No match for " ~ s ~ " of type "
~ typeof(_m).stringof);<br>
}<br>
}<br>
}<br>
<br>Half the complexity and ugliness comes from my wanting to have a variadic function in the end: I did_not_ want have to wrap my arguments in a tuple, as it's done for std.concurrency, IIRC.<br>Also, I use functions like (...) { some code } or (T...)(T t) { } to get a function that matches everything, not a (Variant v) { }<br>
<br>Philippe<br><br></div></div>