https://gist.github.com/pbackus/28e7f5668219ce83467c83c347ec7202
This DIP proposes a conservative design for sum types that aims to be consistent with existing D syntax and semantics. It does not discuss pattern matching.
Thread overview | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
September 12 Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
https://gist.github.com/pbackus/28e7f5668219ce83467c83c347ec7202 This DIP proposes a conservative design for sum types that aims to be consistent with existing D syntax and semantics. It does not discuss pattern matching. |
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Thursday, 12 September 2024 at 02:42:17 UTC, Paul Backus wrote: >https://gist.github.com/pbackus/28e7f5668219ce83467c83c347ec7202 This DIP proposes a conservative design for sum types that aims to be consistent with existing D syntax and semantics. It does not discuss pattern matching. I'm pretty sure I know, but the active field is the one last set, correct? >Access to the tag field of an enum union, if it exists, is always @system. Does this mean I think your example with the The proposal should address taking the address of any member, especially in @safe code. i.e. this is currently allowed:
Such an example would not update the Unless I misunderstand what the "active" field is supposed to be. The proposal should address what happens when you switch types, in terms of lifetime management. Is the prior active field destroyed? Is the memory blitted with field.init before assigning? Is this a construction or an assignment? Is it runtime dependent? None of the examples show an enum union switching types, so maybe I'm misunderstanding something. -Steve |
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | This proposal follows Walter's design in requiring names for elements. This does not match D's library implementations. It does not match how it is used in the literature. It is an improvement, from 8 issues down to 1 that I was able to determine, but unlike Walter's this cannot be fixed. It is core to the design. For the other languages listed, Rust supports names being optional and SML supports the type being optional. |
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Thursday, 12 September 2024 at 02:42:17 UTC, Paul Backus wrote: >https://gist.github.com/pbackus/28e7f5668219ce83467c83c347ec7202 This DIP proposes a conservative design for sum types that aims to be consistent with existing D syntax and semantics. It does not discuss pattern matching. Does the |
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | Paul Backus kirjoitti 12.9.2024 klo 5.42:
> https://gist.github.com/pbackus/28e7f5668219ce83467c83c347ec7202
>
> This DIP proposes a conservative design for sum types that aims to be consistent with existing D syntax and semantics. It does not discuss pattern matching.
You're leaving the implementation of tag field undefined. I think it's better to define it. That way sum types can be used in foreign language APIs, and `sizeof(ASumType)` stays predictable.
Also I propose that the tag type is enumerated type that is implicitly convertible to `int`. The base type is an unsigned integer type big enough to hold all the field types. Default value and the enumerated values (other than having one for each type) can remain unspecified though.
The user should not have to write that `get` function of the example themselves. Otherwise we can't use the sum type from fully `@safe` code if any of it's fields can have unsafe values. Likewise, we should have a generic setter function for all the sum types that type safely checks the tag, and runs the destructor of the old object if the assignment changes the type.
I propose the DIP explicitly allows `void` fields, that work the same way as `Void` fields of TaggedAlgebraic. The void field could be initialised with either `void.init` or `void`. The return reference from `get`ting a void field would point to null. Setting a sumtype to void would simply wouldn't take a value argument.
Overall I like this approach though. Way better than the sum type proposals of Walter and Rikki.
|
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 12 September 2024 at 03:22:07 UTC, Steven Schveighoffer wrote: >I'm pretty sure I know, but the active field is the one last set, correct? Yes. > >Access to the tag field of an enum union, if it exists, is always @system. Does this mean
The tag field is a hidden field whose content is unspecified. Accessing it is They are two different things. >I think your example with the It returns by reference, so no copy constructor is called. >The proposal should address taking the address of any member, especially in @safe code. i.e. this is currently allowed:
Such an example would not update the Good catch. >The proposal should address what happens when you switch types, in terms of lifetime management. Is the prior active field destroyed? Is the memory blitted with field.init before assigning? Is this a construction or an assignment? Is it runtime dependent? None of the examples show an enum union switching types, so maybe I'm misunderstanding something. The intent is that the previous value is destroyed, but you're right that the proposal does not address this. |
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to cookiewitch | On Thursday, 12 September 2024 at 08:55:01 UTC, cookiewitch wrote: >On Thursday, 12 September 2024 at 02:42:17 UTC, Paul Backus wrote: >https://gist.github.com/pbackus/28e7f5668219ce83467c83c347ec7202 This DIP proposes a conservative design for sum types that aims to be consistent with existing D syntax and semantics. It does not discuss pattern matching. Does the The point of the double underscore is to avoid name collision with a user-defined field or method. Ideally, most users would use pattern matching, and never have to check |
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dukc | On Thursday, 12 September 2024 at 09:40:14 UTC, Dukc wrote: >Likewise, we should have a generic setter function for all the sum types that type safely checks the tag, and runs the destructor of the old object if the assignment changes the type. Correction: I think the destructor should run any time the tag changes, even if the new field has the same type as the old one. |
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dukc | On Thursday, 12 September 2024 at 09:40:14 UTC, Dukc wrote: > Paul Backus kirjoitti 12.9.2024 klo 5.42: >> https://gist.github.com/pbackus/28e7f5668219ce83467c83c347ec7202 >> >> This DIP proposes a conservative design for sum types that aims to be consistent with existing D syntax and semantics. It does not discuss pattern matching. > > You're leaving the implementation of tag field undefined. I think it's better to define it. That way sum types can be used in foreign language APIs, and `sizeof(ASumType)` stays predictable. Leaving the tag implementation unspecified allows the compiler to optimize it out. You can use them in foreign languages by defining an extern(C) API and treating the content as opaque. > Also I propose that the tag type is enumerated type that is implicitly convertible to `int`. The base type is an unsigned integer type big enough to hold all the field types. Default value and the enumerated values (other than having one for each type) can remain unspecified though. By "tag type" I assume you mean the type of the __tag property. Is there any practical difference between what you describe and just using size_t? > The user should not have to write that `get` function of the example themselves. Otherwise we can't use the sum type from fully `@safe` code if any of it's fields can have unsafe values. I agree. Ideally, you would use pattern matching to access the fields. But that's a whole separate DIP. > Likewise, we should have a generic setter function for all the sum types that type safely checks the tag, and runs the destructor of the old object if the assignment changes the type. I agree. I'll add to the DIP that the assignment operator should behave like this. > I propose the DIP explicitly allows `void` fields, that work the same way as `Void` fields of TaggedAlgebraic. The void field could be initialised with either `void.init` or `void`. The return reference from `get`ting a void field would point to null. Setting a sumtype to void would simply wouldn't take a value argument. I agree that void fields should be allowed, but that should be a separate DIP, not part of a sum type proposal. They should be allowed for structs and classes too. |
September 12 Re: Enumerated Unions (sum types) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Thursday, 12 September 2024 at 09:56:44 UTC, Paul Backus wrote: >You can use them in foreign languages by defining an extern(C) API and treating the content as opaque. Yes, if the foreign language will only handle it via a pointer. But if the ABI is nailed down, the foreign language can have the sum type on an array or at the stack, and pass them to D functions by value. >I agree. Ideally, you would use pattern matching to access the fields. But that's a whole separate DIP. Pattern matching is complex enough that I agree it's best as it's own DIP. But I think this DIP still needs the simple getter function since a language-level sum type really doesn't carry it's weight if it is too low-level. We already have If you insist, IMO the DIP doesn't necessarily have to specify what exactly the getter function must do, because in the end it's just an utility function. But at least it must be proposed that one should be added to the language or the standard library. >I agree. I'll add to the DIP that the assignment operator should behave like this. I was initially thinking about assignment operator too, but there's a problem. You might have two or more fields with the same type, in which case assigning a value of that type to the sum type is ambiguous. If you instead/also mean an assignment to field of the sum type, then that avoids the problem. >I agree that void fields should be allowed, but that should be a separate DIP, not part of a sum type proposal. They should be allowed for structs and classes too. ...and if they are, we don't need the annoying special case that the setter wouldn't take a value argument for |