Thread overview
Structural exhaustive matching
Apr 21, 2015
Jadbox
Apr 21, 2015
bearophile
Apr 21, 2015
weaselcat
Apr 21, 2015
Justin Whear
Apr 21, 2015
Jacob Carlborg
Apr 22, 2015
Martin Nowak
Apr 22, 2015
weaselcat
April 21, 2015
What's the best equivalent to Rust's structural enum/pattern (match)ing? Is it also possible to enforce exhaustive matches? Basically, I'm curious on what the best way to do ADTs in D.
April 21, 2015
Jadbox:

> I'm curious on what the best way to do ADTs in D.

Sometimes there's no best way, there are several alternative ways with different tradeoffs. D isn't a functional language and there's no really good way to do ADTs in D. You can use plus a "final switch". Or you can use Algebraic from Phobos. Sometimes you can use another Phobos function that simulates an improved switch. Or often you can just give up at using ADTs in D and use what other solutions D offers you (like OOP).

Bye,
bearophile
April 21, 2015
On Tuesday, 21 April 2015 at 15:36:28 UTC, Jadbox wrote:
> What's the best equivalent to Rust's structural enum/pattern (match)ing? Is it also possible to enforce exhaustive matches? Basically, I'm curious on what the best way to do ADTs in D.

D's ADTs are in std.variant, the equivalent of matching is the .visit property AFAIK
April 21, 2015
On Tue, 21 Apr 2015 15:36:27 +0000, Jadbox wrote:

> What's the best equivalent to Rust's structural enum/pattern (match)ing?
> Is it also possible to enforce exhaustive matches?
> Basically, I'm curious on what the best way to do ADTs in D.

std.variant.Algebraic implements ADTs:

import std.variant, std.string;
struct Foo { ... }
alias A = Algebraic!(int, double, Foo);
A a = 1;

// std.variant.visit enforces that all possible types are handled, so this
//  is an error:
auto res = a.visit!(
	(int x) => format("Got an int: %s", x),
	(double x) => format("Got a double: %s", x),
	(Foo x) => "Got a Foo"
);

You can also dispatch to a function with the appropriate overloads/ template instantiations like so:

foreach (T; A.AllowedTypes)
	if (a.type is typeid(T))
		myfunc(a.get!T);

This also exhaustively guarantees that myfunc can be called with all possible types of a.
April 21, 2015
On 2015-04-21 17:36, Jadbox wrote:
> What's the best equivalent to Rust's structural enum/pattern (match)ing?
> Is it also possible to enforce exhaustive matches? Basically, I'm
> curious on what the best way to do ADTs in D.

There's something call "castSwitch" [1], perhaps not what you're looking for.

[1] http://dlang.org/phobos/std_algorithm_comparison.html#.castSwitch

-- 
/Jacob Carlborg
April 22, 2015
On Tuesday, 21 April 2015 at 15:36:28 UTC, Jadbox wrote:
> What's the best equivalent to Rust's structural enum/pattern (match)ing? Is it also possible to enforce exhaustive matches? Basically, I'm curious on what the best way to do ADTs in D.

If it needs to be really fast, use final switch on the tag of a discriminated union.

enum Tag { A, B, C }
struct Val
{
  Tag tag;
  union
  {
    A a;
    B b;
    C c;
  }
}

void too(Val val)
{
  final switch (val.tag)
  {
  case Tag.A: writeln(val.a); break;
  case Tag.B: writeln(val.b); break;
  case Tag.C: writeln(val.c); break;
  }
}
April 22, 2015
On Wednesday, 22 April 2015 at 04:54:39 UTC, Martin Nowak wrote:
> On Tuesday, 21 April 2015 at 15:36:28 UTC, Jadbox wrote:
>> What's the best equivalent to Rust's structural enum/pattern (match)ing? Is it also possible to enforce exhaustive matches? Basically, I'm curious on what the best way to do ADTs in D.
>
> If it needs to be really fast, use final switch on the tag of a discriminated union.
>
> enum Tag { A, B, C }
> struct Val
> {
>   Tag tag;
>   union
>   {
>     A a;
>     B b;
>     C c;
>   }
> }
>
> void too(Val val)
> {
>   final switch (val.tag)
>   {
>   case Tag.A: writeln(val.a); break;
>   case Tag.B: writeln(val.b); break;
>   case Tag.C: writeln(val.c); break;
>   }
> }

there's no reason this should be faster than Algebraic(restricted variant) from std.variant, is there? implementation issue?