Thread overview
sumtype 0.8.3
Feb 26
JN
February 25
SumType is a generic sum type for modern D. It is meant as an alternative to
`std.variant.Algebraic`.

Features:
  - Pattern matching, including support for structural matching (★)
  - Self-referential types, using `This`
  - Works with pure, @safe, @nogc, and immutable (★)
  - Zero runtime overhead compared to hand-written C
    - No heap allocation
    - Does not rely on runtime type information (`TypeInfo`) (★)

Starred features (★) are those that are missing from `Algebraic`.

Code examples are available in the documentation (linked below).

New since the last announced version, 0.7.0:
  - SumType now accepts non-copyable types as members.
  - A new template, `canMatch`, allows querying the matching logic directly.
  - A bug in the `==` operator of self-referential SumTypes has been fixed.
  - An exception-safety bug in SumType's assignment operator has been fixed.
  - The documentation and examples have been given some additional polish.

Special thanks to Atila Neves and John Colvin for their contributions to this
release.

Links:
  - Documentation: https://pbackus.github.io/sumtype/sumtype.html
  - DUB: https://sumtype.dub.pm
  - Github: https://github.com/pbackus/sumtype
February 26
On Monday, 25 February 2019 at 20:31:43 UTC, Paul Backus wrote:
> SumType is a generic sum type for modern D. It is meant as an alternative to
> `std.variant.Algebraic`.

Is it a better alternative? Seems like it from the description. If it's objectively better on all fronts, perhaps it should be considered for inclusion into Phobos, as a replacement for the existing Algebraic?
February 26
On Tuesday, 26 February 2019 at 12:52:11 UTC, JN wrote:
> On Monday, 25 February 2019 at 20:31:43 UTC, Paul Backus wrote:
>> SumType is a generic sum type for modern D. It is meant as an alternative to
>> `std.variant.Algebraic`.
>
> Is it a better alternative? Seems like it from the description. If it's objectively better on all fronts, perhaps it should be considered for inclusion into Phobos, as a replacement for the existing Algebraic?

It's not a perfect superset of Algebraic and Variant in Phobos, so it's not a strictly better alternative. The feature that is missing is SumType can't hold arbitrary types, only the types specified in its template parameters. However, for the case where the set of possible types is limited, it's strictly better.

--
  Simen
February 26
On Tuesday, 26 February 2019 at 12:52:11 UTC, JN wrote:
> On Monday, 25 February 2019 at 20:31:43 UTC, Paul Backus wrote:
>> SumType is a generic sum type for modern D. It is meant as an alternative to
>> `std.variant.Algebraic`.
>
> Is it a better alternative? Seems like it from the description. If it's objectively better on all fronts, perhaps it should be considered for inclusion into Phobos, as a replacement for the existing Algebraic?

SumType isn't a drop-in replacement for Algebraic (e.g., it removes some unsafe methods like `peek`), so it would have be included in addition to Algebraic, rather than instead of it.

That said, if Walter, Andrei, and the rest of the Phobos team are ok with having two implementations of essentially the same thing in the standard library, I think SumType has reached a level of stability where I'd be comfortable submitting it for inclusion.
March 03
On Monday, 25 February 2019 at 20:31:43 UTC, Paul Backus wrote:
>   - Pattern matching, including support for structural matching (★)

What is the main difference between 'match()' in this library and 'visit()' in std.variant?
March 04
On Sunday, 3 March 2019 at 14:32:55 UTC, Jacob Shtokolov wrote:
> On Monday, 25 February 2019 at 20:31:43 UTC, Paul Backus wrote:
>>   - Pattern matching, including support for structural matching (★)
>
> What is the main difference between 'match()' in this library and 'visit()' in std.variant?

I'm glad you asked! There are quite a few differences between SumType's `match` and Algebraic's `visit`. For a comprehensive answer, I recommend reading and comparing the documentation for both [1][2], but I'll do my best to highlight some of SumType's biggest advantages here.

1. `match` uses static introspection to determine whether a handler can be used for a particular type. This allows it to be much more flexible that `visit`, which requires an exact match. For example:

    alias CharSequence = SumType!(char[], immutable(char)[]);

    char firstChar(CharSequence seq) {
        return seq.match!((const(char)[] arr) => arr[0]);
    }

Because both `char[]` and `immutable(char)[]` can be passed to a function that accepts `const(char)[]`, `match` allows you to use the same handler for both types, even though it doesn't match either one exactly. With `visit`, that's not allowed.

2. `match` will also allow you to leave out type annotations altogether, if it can figure out what the right matches are from the function bodies. For example:

    alias Value = SumType!(int, double, string);

    void double(Value v) {
        v.match!(
            (ref number) { number *= 2; }
            (ref array) { array ~= array; }
        );
    }

In the code above, `match` is able to tell (using `__traits(compiles)`) that you can only use `*=` with a number, so that function should be used for the int and float members, and you can only use `~=` with an array, so that function should be used for the string member. This is what's referred to as "structural matching" in the announcement post, though now that I think of it, "introspection-based matching" is probably a better name.

Once again, `visit` can't do this at all--if you try to write the equivalent of the above code, it simply won't compile.

3. `match` gives you an error if you pass it a handler that doesn't match *any* of the types in your SumType. For example, the following code won't compile:

    alias Value = SumType!(int, double);

    int floor(Value v) {
        return v.match!(
            (int i) => i,
            (double d) => cast(int) d,
            (string s) => cast(int) s.to!double // Error: handler #3 never matches
        );
    }

This error is useful to have when you remove a member from your SumType, since it ensures you won't miss any code that needs updating. It also helps with introspection-based mapping, since it can catch cases where one function accidentally "shadows" another. `visit`, meanwhile, will let you pass it as much garbage as you want.

[1] https://dlang.org/phobos/std_variant.html#.visit
[2] https://pbackus.github.io/sumtype/sumtype.match.html
March 05
On Monday, 4 March 2019 at 00:46:12 UTC, Paul Backus wrote:
>

Thank you, that's a very good explanation!
It seems that 'match' is a lot better than 'visit'.

Probably it'd be better to have this library as a replacement of std.variant in Phobos.