March 18, 2021
On 3/18/21 12:11 PM, Paul Backus wrote:
> On Thursday, 18 March 2021 at 15:58:55 UTC, Oleg B wrote:
>> auto tag = val.match!(
>>   (Type1 t1) => 0, // or MyOwnValTag.type1
>>   (Type2 t2) => 1, // or MyOwnValTag.type2
>>   ... etc
>> );
>>
>> next write tag, in next match write value
>>
>> how to generate this match without mixins? how to get (in general way) type from sumtype val by own tag or number for deserialization?
> 
> Something like this:
> 
> alias QualifiedTypes = CopyTypeQualifiers!(typeof(val), val.Types);
> auto tag = val.match!(v => staticIndexOf!(typeof(v), QualifiedTypes));

Wait, you can't access the tag for the tagged union?

FYI, taggedalgebraic, it's simply val.kind.

I'd suggest giving read-only access to the tag. The types are already accessible.

-Steve
March 18, 2021
On Thursday, 18 March 2021 at 16:34:15 UTC, Oleg B wrote:
> On Thursday, 18 March 2021 at 16:11:06 UTC, Paul Backus wrote:
>> Something like this:
>>
>> alias QualifiedTypes = CopyTypeQualifiers!(typeof(val), val.Types);
>> auto tag = val.match!(v => staticIndexOf!(typeof(v), QualifiedTypes));
>
> why it is not in library? or why tag is private?

Because I personally haven't needed it for anything, and nobody else has presented me with a convincing use-case for it until now.

In general, it is much, much easier to add new features than to remove existing ones, so I try to put off adding a feature until I am absolutely sure it is the right decision.
March 18, 2021
On Thursday, 18 March 2021 at 16:48:01 UTC, Paul Backus wrote:
> Because I personally haven't needed it for anything, and nobody else has presented me with a convincing use-case for it until now.
>
> In general, it is much, much easier to add new features than to remove existing ones, so I try to put off adding a feature until I am absolutely sure it is the right decision.

Adding read-only tag is simple and useful change. If I understand code correctly tag is direct index of val.Types, it's right?

May be depending on order of types must be fixed too

```
alias S1 = Sumtype!(int, float);
alias S2 = Sumtype!(float, int);

static assert (is(S1 == S2)); // false by now
```
because no different between S1 and S2 in practice use
March 18, 2021
On 3/18/21 1:24 PM, Oleg B wrote:
> May be depending on order of types must be fixed too
> 
> ```
> alias S1 = Sumtype!(int, float);
> alias S2 = Sumtype!(float, int);
> 
> static assert (is(S1 == S2)); // false by now
> ```
> because no different between S1 and S2 in practice use

That requires sorting the types somehow, which isn't really easy or cheap at compile-time.

It's the same for std.variant.Algebraic (although it's a runtime error instead of a compile-time one).

It's kind of a tradeoff that you have to live with -- nice type checking, but you have to keep the same order for sanity.

-Steve
March 18, 2021
On Thursday, 18 March 2021 at 17:39:04 UTC, Steven Schveighoffer wrote:
> That requires sorting the types somehow, which isn't really easy or cheap at compile-time.
>
> It's the same for std.variant.Algebraic (although it's a runtime error instead of a compile-time one).
>
> It's kind of a tradeoff that you have to live with -- nice type checking, but you have to keep the same order for sanity.
>
> -Steve

As I know it solved in mir.algebraic [1] and code for solving isn't complicated [2] but it will be good if it be in library.

[1] http://mir-core.libmir.org/mir_algebraic.html

[2] example for some kind of tuple
```
struct Bar(T...) { T val; }

template Foo(T...)
{
    enum CmpTypes(T1, T2) = fullyQualifiedName!T1 < fullyQualifiedName!T2;
    alias Foo = Bar!(staticSort!(CmpTypes, T));
}
```
March 18, 2021
I'm not a fan of the syntax.. why is it a library instead of a language feature?..

```
Fahrenheit toFahrenheit(Temperature t)
{
    return Fahrenheit(
        t.match!(
            (Fahrenheit f) => f.degrees,
            (Celsius c) => c.degrees * 9.0/5 + 32,
            (Kelvin k) => k.degrees * 9.0/5 - 459.4
        )
    );
}
```

vs

```
Fahrenheit toFahrenheit(Temperature t)
{
    return match(t) {
            (Fahrenheit f) => f.degrees,
            (Celsius c) => c.degrees * 9.0/5 + 32,
            (Kelvin k) => k.degrees * 9.0/5 - 459.4
    };
}
```

I don't understand why make things confusing when it can be done simpler

Discriminated union should be a language feature, not lib!

Because now you depend on ``std``

March 18, 2021
On Thursday, 18 March 2021 at 17:24:13 UTC, Oleg B wrote:
> May be depending on order of types must be fixed too
>
> ```
> alias S1 = Sumtype!(int, float);
> alias S2 = Sumtype!(float, int);
>
> static assert (is(S1 == S2)); // false by now
> ```
> because no different between S1 and S2 in practice use

union U1 { int n; float f; }
union U2 { float f; int n; }

static assert(is(U1 == U2)); // fails

D is a nominally-typed language, not a structurally-typed one. That means types that are structurally identical (like the unions and SumTypes in the above examples) are still considered separate types if their names are spelled differently.

IMO the behavior of SumType in this regard is perfectly consistent with the rest of the language. If you want to use structural typing instead of nominal typing in your own code, you can define template predicates to check for SumTypes with a particular structure, the same way Phobos defines predicates like `isInputRange` to check for types with a particular structure.
March 18, 2021
On Thursday, 18 March 2021 at 18:06:45 UTC, ryuukk_ wrote:
> I'm not a fan of the syntax.. why is it a library instead of a language feature?..

Because it's easier to write a library than to go through the whole process of writing a DIP for a new language feature, getting it accepted, and implementing it in the compiler.

If you or anyone else wants to write a DIP to add sum types to D as a language feature, I will happily support the effort, but I am not going to do it myself.

> Because now you depend on ``std``

`std.sumtype` has no non-optional dependencies on Phobos outside of compile time, so you can use it even if you do not want to depend on anything else in `std`.
March 18, 2021
On Thursday, 18 March 2021 at 18:15:29 UTC, Paul Backus wrote:
> On Thursday, 18 March 2021 at 18:06:45 UTC, ryuukk_ wrote:
>> I'm not a fan of the syntax.. why is it a library instead of a language feature?..
>
> Because it's easier to write a library than to go through the whole process of writing a DIP for a new language feature, getting it accepted, and implementing it in the compiler.
>
> If you or anyone else wants to write a DIP to add sum types to D as a language feature, I will happily support the effort, but I am not going to do it myself.
>
>> Because now you depend on ``std``
>
> `std.sumtype` has no non-optional dependencies on Phobos outside of compile time, so you can use it even if you do not want to depend on anything else in `std`.


That's how i feel about it, people didn't care enough and easiest solution picked (let's put this lib instead), now you have to use a feature, as a lib, calling functions that looks like template functions, in the end it is confusing

i can switch(t), but i can't match(t), i need to use a different syntax
March 18, 2021
> More general question: why phobos so bad structured? No way to determine what can be used without gc, that need it (other D features like betterC in the same situation). Some basic actions requires couple of std libs (std.file, std.path etc). Why something things placed in experimental will be in experimental during several years, other placed to std directly (sumtype)?
>
> May be it's time to restructure std, and determine algorithm for place new code to it (like DIPs)?

I agree 1000% things are confusing when you want to manage memory yourself, you either have to check every functions and see if they allocate or no, or force yourself to add @nogc everywhere

OR use @betterC and have access to no std at all

I personally picked the @betterC option and use D like i'd use C/C++, and it feels much better, i have my own Allocator struct, and whenever i need to allocate memory, i ask for an allocator

If only the std was designed like this, whenever you want to allocate, you ask user to provide an allocator

Want use GC? use gc allocator, everyone wins