-
Notifications
You must be signed in to change notification settings - Fork 213
Unions as parameters #3608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Definitely possible. The linked proposal tries to deliberately avoid some of the complexities of structural union types, which is why it choses to not allow you to write a union type without giving it a name. What you have here is probably either structural union types, but only in parameter position, or general union types. |
Dart already has a way of defining sealed union in OOP style: sealed class UrlThingy {}
class UrlCase extends UrlThingy {
final Url url;
UrlCase(this.url);
}
class StrCase extends UrlThingy {
final String string;
StrCase(this.string);
} P.S. Though I find it very convenient to use the same patterns I use in typescript, it's often useful to understand why one language has some feature, while other doesn't. Dart is mostly OOP language with some QoL features from functional paradigm. So in Dart you write (mostly) in OOP style. If you need to define common operation on UrlThingy in your code, you would have to write a function which accepts the same union and then branch out implementations (which is purely functional style). In my solution above, it would be defined on UrlThingy as abstract method (which IMO is the right place) and then implemented in every case. |
Yes, this is well known. It's also much more verbose. |
Sealed types in Dart model sum types, not union types. This article does a good job of explaining the difference. |
This isn't quite the same thing as union types... This seems more like defining a new |
you can do anything... "one" | "two" | int, anything is allowed. I just gave a practical example, where making your own enum for this single usage is completely unpractical and hard, because once you have 40 values you need 40 enums. |
Sorry, let me clarify. I wasn't trying to say what you were suggesting shouldn't be allowed, I was just explaining that the concept of a "value union" ( To your point however, the shared syntax is interesting. I'd be curious to explore how
Not sure I understand what you mean here... Do you mean you would need a new name for each type of Edit: Thinking about this more, I would actually suggest clarifying in the docs for this feature that this is not a replacement for |
I think "one" | "two" is just a consequence and should be allowed as well. Just like |
For this issue's feature request (that is, "type unions"), I don't think // an example of "type unions", what this issue suggests
void myFunction(int | String intOrString) {
print(intOrString); // prints 1 or -15 or "some string"
print(intOrString.runtimeType); // either prints "int" or "String"
switch (intOrString) {
case int():
// when `intOrString is int` and has 1, -15, etc. as its value
case String():
// when `intOrString is String` and has "some string", etc. as its value
}
} and this code // an example of "value unions", what you're suggesting
void myFunction(int | String intOrString) {
print(intOrString); // prints "int" or "String"
print(intOrString.runtimeType); // always prints "Type"
switch (intOrString) {
case int:
// when `intOrString == int`, aka has `int` as its value (not 1, -15, etc)
case String:
// when `intOrString == String`, aka has `String` as its value (not "some string", etc)
}
} Where you've made an argument for the benefits of what you're talking about, I'd suggest making a new, separate issue where you can specify your idea and the use cases you came up with. I think your idea deserves it. |
But switch already has full support into distinguishing it, the only thing
missing is a type to make this possible.
…On Fri, Jun 7, 2024, 19:35 Taylor Brown ***@***.***> wrote:
I think "one" | "two" is just a consequence and should be allowed as well.
For this issue's feature request (that is, "type unions"), I don't think "one"
| "two" would be a (simple) consequence of adding the feature. As I said
before, what you're suggesting is more like "value unions" or anonymous
enums rather than "type unions". The distinction is important because of
the possible syntax clash, and would require a different
spec/implementation in the guts of dart to get it working than the
proposal referenced by this issue
<https://github.com/dart-lang/language/blob/main/working/union-types/nominative-union-types.md>.
What I mean by "the distinction" is that int | String could mean two
different things, and is the difference between this code
// an example of "type unions", what this issue suggestsvoid myFunction(int | String intOrString) {
print(intOrString); // prints 1 or -15 or "some string"
print(intOrString.runtimeType); // either prints "int" or "String"
switch (intOrString) {
case int():
// when `intOrString is int` and has 1, -15, etc. as its value
case String():
// when `intOrString is String` and has "some string", etc. as its value
}
}
and this code
// an example of "value unions", what you're suggestingvoid myFunction(int | String intOrString) {
print(intOrString); // prints "int" or "String"
print(intOrString.runtimeType); // always prints "Type"
switch (intOrString) {
case int:
// when `intOrString == int`, aka has `int` as its value (not 1, -15, etc)
case String:
// when `intOrString == String`, aka has `String` as its value (not "some string", etc)
}
}
Where you've made an argument for the benefits of what you're talking
about, I'd suggest making a new, separate issue where you can specify your
idea and the use cases you came up with. I think your idea deserves it.
—
Reply to this email directly, view it on GitHub
<#3608 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACVXFISI6YDY6HQGKWCUB3ZGIYRZAVCNFSM6AAAAABC2YCI66VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJVGY2TMOBWG4>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
When the "only thing missing" is a completely new kind of type added to the type system, that still deserves its own issue. It's not a union type in the normal meaning of that's phrase, because it's not a union of types. If every value was its own "type", then this kind of types would be a consequence of union types. |
The "union of values" can be modelled as an enum: abstract class RawValue<T> {
T get rawValue;
}
enum Answer implements RawValue<String> {
one("one"),
two("two"),
three("three");
final String rawValue;
const Answer(this.rawValue);
} This is roughly how Swift implements the feature, though it provides an extra layer of (magic) sugar: enum CompassPoint: String { // extending String triggers magic emergence of "rawValues"
case north, south, east, west
}
let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west" |
I read https://github.com/dart-lang/language/blob/main/working/union-types/nominative-union-types.md, and see the proposed syntax is something like:
Could we just do:
The text was updated successfully, but these errors were encountered: