<br><br><div class="gmail_quote">On Sun, Apr 4, 2010 at 17:18, Lutger <span dir="ltr">&lt;<a href="mailto:lutger.blijdestijn@gmail.com">lutger.blijdestijn@gmail.com</a>&gt;</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>
&gt; I&#39;m not currently asking to implement pattern matching in D3 (as present<br>
&gt; for example in Scala), but it&#39;s positive to think how to solve similar<br>
&gt; problems in D2, because even if pattern matching is not available in D2,<br>
&gt; the problems it is asked to solve solve can be real.<br>
&gt;<br>
&gt; Walter or Andrei has recently shown here a possible implementation idea,<br>
&gt; but I don&#39;t remember where the post is and what the implementation was. And<br>
&gt; it wasn&#39;t a small compilable program.<br>
<br>
</div>It was a subthread under the &#39;is D a cult&#39; thread, this was the basic<br>
example:<br>
<br>
foo(  v,<br>
      (int i) { writeln(&quot;I saw an int &quot;, i); },<br>
      (string s) { writeln(&quot;I saw a string &quot;, s); ),<br>
      (Variant any) { writeln(&quot;I saw the default case &quot;, 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 &quot;any: &quot; ~ 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 ~ &quot; thrice&quot;;}<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,&#39;a&#39;); // Tuple!(int,char)(1,&#39;a&#39;)<br>auto m = matcher(1,2,3,4); // string &quot;any: (int,int,int,int)&quot;<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&#39;s far from being as beautiful as Haskell code, but it&#39;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&#39;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 &amp;&amp; is(typeof(fun(_m[0])))) // I&#39;m not sure this is necessary<br>
            return fun(_m[0]);<br>
        else static if (Rest.length &gt; 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(&quot;No match for &quot; ~ s ~ &quot; of type &quot;
 ~ 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&#39;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>