November 29, 2022
On 11/29/22 07:26, Walter Bright wrote:
> Go ahead, Make My Day! Destroy!
> 
> https://github.com/WalterBright/DIPs/blob/sumtypes/DIPs/1NNN-(wgb).md

>

BTW: I understand extraordinarily well where the desire for supporting an explicitly nullable pointer comes from, but I worry that integrating it into the more general syntax implicitly is a bit too cute. It will lead to bad interactions in generic code.

E.g.:

sumtype WithDefault(T){
    Default;
    T Value;
}

A user does not expect this to behave specially if `T` is a pointer. Generic code would have to explicitly check for that case and manually undo the rewrite in the library. I don't want to read the resulting unwieldy Phobos code.

Explicitly nullable pointers are too good of a feature to just give up though, so instead, you could introduce explicit syntax for the null check.

E.g.:

sumtype Nullable{
    Null,
    int* Ptr;
    invariant(Ptr !is null);
}

The semantics of this would be to check the invariant on assignment and if it fails, then default-initialize the type instead. There could be multiple invariants that each can only refer to one of the members.

Then this would be distinct from:

sumtype DoublyNullable{
    Null,
    int* Ptr;
}

It would also be more general because it allows enforcing more general invariants. (But it could also be limited to the special case with null, at least in the beginning; what's important is that the different behavior is documented explicitly in a difference in syntax.)

Note that with the semantics where a bad member access is a runtime error, you don't gain much over just using a raw pointer. Therefore, I really think D should statically enforce that the user checks the tag.
November 29, 2022
On 11/29/22 07:26, Walter Bright wrote:
> Go ahead, Make My Day! Destroy!
> 
> https://github.com/WalterBright/DIPs/blob/sumtypes/DIPs/1NNN-(wgb).md


Maybe consider changing the syntax to something like:

sumtype ST{
    a;
    int* b;
}

The reason is that with comma-separated values, metaprogramming is hobbled.

I think we really want to be able to do things like:

sumtype ST(bool hasC){
    a;
    int* b;
    static if(hasC){
        float c;
    }
}

Similar for `static foreach`. The fact that this does not work for `enum`s is among the most annoying limitations of `enum`s.
November 29, 2022
On 11/29/22 07:26, Walter Bright wrote:
> Go ahead, Make My Day! Destroy!
> 
> https://github.com/WalterBright/DIPs/blob/sumtypes/DIPs/1NNN-(wgb).md

Maybe you want to consider this example:

struct S(T...){
    T members;
}

I guess this creates multiple cases, but it's a good thing to keep in mind, also for the implementation.
November 29, 2022
On 11/29/22 07:26, Walter Bright wrote:
> Go ahead, Make My Day! Destroy!
> 
> https://github.com/WalterBright/DIPs/blob/sumtypes/DIPs/1NNN-(wgb).md

Another thing to consider:

sumtype A{
    int a;
    B b;
}

sumtype B{
    int c;
    int d;
}

Is the following allowed?

A a;
...
if(?a.b.c){ ... }
November 29, 2022
On 11/29/22 14:45, rikki cattermole wrote:
> 
> "Members of sumtypes cannot have copy constructors, postblits, or destructors."
> 
> Kills reference counting, can't use it. Can't use it for value typed exceptions as the underlying sum type implementation. Not good enough. Note when these are not defined you can optimize the copying to be just mov's.
> 

Oof. Missed that bit. Yes, that limitation won't fly. This must be supported.

November 29, 2022
On 11/29/22 09:40, Andrey Zherikov wrote:
> Few other things that I think should be clarified:
> 
> Will sumtype support UDAs for its members?

It should, just like for `enum` and `union`.

> How will __traits work for sumtype (especially `allMembers` and `getMember`)?

I guess it should work just like for `enum` and `union`.
November 29, 2022
On Tuesday, 29 November 2022 at 14:51:34 UTC, Timon Gehr wrote:
> On 11/29/22 07:26, Walter Bright wrote:
>> Go ahead, Make My Day! Destroy!
>> 
>> https://github.com/WalterBright/DIPs/blob/sumtypes/DIPs/1NNN-(wgb).md
>
> Another thing to consider:
>
> sumtype A{
>     int a;
>     B b;
> }
>
> sumtype B{
>     int c;
>     int d;
> }
>
> Is the following allowed?
>
> A a;
> ...
> if(?a.b.c){ ... }

More importantly does it support?

sumtype A{
    Null;
    A a;
}

If so, are their any plans for default initialization using the GC when it comes to chaining?

I.E.

a.?a.?a

or custom syntax when returning a default value if it said sumtype is determined at run time to have a null type?
I.E.

int x = a.a ?? 0;
without having to type
if(?a.a)
{
int x = a.a;
}
else
{
int x = 0;
}
or using the ternary conditional operator for this?

- Alex
November 29, 2022

On Tuesday, 29 November 2022 at 14:45:09 UTC, Timon Gehr wrote:

>

On 11/29/22 07:26, Walter Bright wrote:

>

Go ahead, Make My Day! Destroy!

https://github.com/WalterBright/DIPs/blob/sumtypes/DIPs/1NNN-(wgb).md

Some things that are missing:

  • non-default construction, e.g.:

sumtype Result{
error,
int value;
}

auto result1 = Result.error;
auto result2 = Result.value(2);

The above is a bit unergonomic, maybe there is a better way to expose those constructors. They should exist though, otherwise it is e.g., impossible to initialize an immutable sumtype.
[snip]

I was a little confused because the DIP proposal has the same example (though using Error instead of error) and it didn't have an identifier with it. According to the syntax, a field declaration has to have an identifier with the type. So the only other option is Error/error is an enum. If that's the case, it's a little confusing because Error is a commonly used class already.

Am I right that if you wanted to do the same as below

import std.sumtype;
struct Fahrenheit { double degrees; }
struct Celsius { double degrees; }
struct Kelvin { double degrees; }

alias Temperature = SumType!(Fahrenheit, Celsius, Kelvin);

then the equivalent with this DIP would be

sumtype Temperature
{
    Fahrenheit fahrenheit,
    Celsius celsius,
    Kelvin kelvin
}
November 30, 2022
On 30/11/2022 4:10 AM, 12345swordy wrote:
> More importantly does it support?
> 
> sumtype A{
>      Null;
>      A a;
> }

At least in the theory that Null is equivalent to None which should be added to our type system and not just defined inline (as it is an existing hole).

Question is what to do when you do want to store that typed null.
November 30, 2022
Something else I want to talk a bit more on.

Sumtypes are not distinct in the type system. They are like alias, its just a collection of values/behavior that is given a name.

You would need to use features like templates, conditional compilation, UDA's ext. to make it distinct and even then they should be implicitly convertible as long as its a superset or equal in members.

This extends over to the AST implementation stuff, it means there would need to be a global table containing the actual instances and when you instantiate a templated sumtype the instance would effectively be just an alias into an entry in that table.

Like None, the non-distinctiveness of sumtypes is fundamental in the type theory and comes from set theory. So its important that we get this right, because it has a lot of flow on effects.