On Monday, 26 October 2015 at 11:40:09 UTC, Edmund Smith wrote:
On Sunday, 25 October 2015 at 06:22:51 UTC, TheFlyingFiddle wrote: You could also emulate constant matching using default parameters (albeit with the restriction that they must be after any non-default/constant parameters), since the defaults form part of the function's type. I tried making something like this earlier this summer and it'd check that a given value was first equal to the default parameter and match if so, or match if there was no default parameter but the types matched.

e.g.
//template ma(tch/g)ic

unittest
{
    Algebraic!(string, int, double, MyStruct) v = 5;
    string s = v.match!(
        (string s = "") => "Empty string!",
        (string s) => s,
        (int i = 7) => "Lucky number 7",
        (int i = 0) => "Nil",
        (int i) => i.to!string,
        (double d) => d.to!string,
        (MyStruct m = MyStruct(15)) => "Special MyStruct value",
        (MyStruct m) => m.name, //
        () => "ooer");
    writeln(s);
}

It's a bit ugly overloading language features like this, but it makes the syntax a little prettier.
This does look nicer indeed.

Why not just use a value as an extra argument:
v.match!(
   7, (int i) => "Lucky number 7"
);
I like this you could go further with this to allow any number of constants.
v.match!(
    5, 7,   i => "Was: " ~ i.to!string,
    (int i)   => "Was this: " ~ i.to!string);

Or for ranges.
v.match!(
    MatchR!(1, 10), i => "Was: " ~ i.to!string, //Matches 1 .. 10
    (int i)          => "Was this: " ~ i.to!string);

I'd really like to see proper pattern matching as a language-level feature however; for all the emulating it we can do in D, it's not very pretty or friendly and optimising it is harder since the language has no concept of pattern matching.
One could probably get something like this:

int i = 5;
string s = i.match!(
   5, 7, n => "Five or seven",
   MatchR!(10, 100), n => "Was between ten and a hundred",
   (n)     => "Was: " ~ n.to!string);

to fold into something like this:

void match(T...)(int i)
{
   switch(i)
   {
      case 5: case 7: return (T[2])!int(i);
      case 10: .. case 99: return (T[3])!int(i);
      default: return (T[4])!int(i);
   }
}

int i = 5;
string s = match!(/* lambdas and whatnot */), i);

With some template/ctfe and string mixings magic.

In-lining, constant folding etc could probably just reduce it to
the equvalent of:

int i    = 5;
string s = "Five or seven";

(if there is really good constant folding :P)

It might however generate lot's of useless symbols in the resulting code
making code size's larger.

Things like Option (and other ADTs) are lovely, but really need good pattern matching to become worthwhile IMO (e.g. Java Optional<T> has a get() method that throws on empty, which undermines the main reason to use optional -
Another thing that has always bothered me with Optional<T> in Java in addition to this is that the optional value itself might be null. So to write robust code you first have to check against null on the option value :P.

Scala's Option is really nice on the other hand since you can/should pattern match).
Don't really see a point in an optional type if can access the underlying
value without first checking if it's there.




Reply via email to