-
Notifications
You must be signed in to change notification settings - Fork 205
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
Parameter destructuring #3001
Comments
Definitely something I want. I really want declaration patterns everywhere a value is checked/ensured to be a type.
The biggest question here is whether the leading int example(var Abc(:i)) => i;
// or
int example(Abc(:var i)) => i; The former is more consistent with existing declaration patterns, so I'd say it's the more likely approach. The alternative is to see a parameter list as one big declaration pattern to begin with, so no extra The other issue is that we want to give a parameter a name, even though a pattern declaration doesn't have one. void foo({(:int x, :int y) point}) => ... needs the name. (And then, can Some design space to go through here. |
Will this be possible: void printXY(({int x, int y, _ /* ignore rest */})) {
print('x: $x, y: $y');
}
printXY((x: 0.0, y: 0.0));
printXY((x: 0.0, y: 0.0, z: 0.0)); |
@ykmnkmi That's a good question; I'm curious as to the response on that. @lrhn about named/positional parameters: at a certain point here, I think it would almost make sense to just unify the function parameter and record syntax since they are so similar, and then this issue would probably become much easier to handle from a design perspective. (At that point, I believe you wouldn't need to worry about named parameters anymore, and can instead just focus on the names used within the destructuring?) I remember seeing mention of the Dart/Flutter teams wanting a syntax like this: MyWidget(
positionalArgument,
someNamedParam: 1234,
if (someOtherProperty) someOtherNamedParam: Foo.bar, // conditionally passing argument Wouldn't that also require parameters to be treated in a similar manner to records? Maybe this issue could be tackled together with that one. (Thought process: if you can conditionally pass an argument to a record, and function parameters are treated similarly to records, then it'd be much easier to conditionally pass an argument to a function?) |
I'm with @lrhn in that I would like to support destructuring patterns in parameter lists, yes. But Dart 3.0 won't support that. The problem is that the parameter list syntax is already very complex and, in particular, uses So figuring out how to jam some or all of the pattern syntax into that already dense (and, frankly, not that great) parameter grammar is really hard, possibly intractable. One thing we probably could do is support destructuring record fields when a parameter type is a record type annotation. This wouldn't allow arbitrary patterns in parameters, but would at least allow: takePair((int x, int y) pair) {
print('$x $y');
}
main() {
var pair = (1, 2);
takePair(pair);
}
No, it won't. We don't do "width subtyping" for records, and we don't allow you to work with "part" of a record whose remaining shape is unknown. Being polymorphic over record shapes in this way can lead to a lot of complexity and potentially make code size and performance worse. To avoid that, whenever you're working with a record in Dart, the compiler always knows its entire shape and all of its fields. |
Hey, I wanted to add a use case: When using indexed on an Iterable: int getMaxChildIndexForScrollOffset(double scrollOffset) {
return myItems
.indexed
.lastWhere((_, final item) => item.startOffset + item.height <= scrollOffset)
.$1;
} Edit:Regarding pattern matching in Rust, the Axum web framework makes heavy use of that feature, in that the User can declaratively specify what they want their handlers to handle, instead of manually having to destructure and Deserialize Requests, Query-strings or JSONs and then rejecting if they don't match. Obviously this is all implemented by that crate and not the language feature that allows destructuring / pattern matching in that position, but I think it serves as a less academic example for why it's a useful feature. docs.rs/axum/latest/axum/extract/index.html#common-extractors |
I tried a few variants of the following, and was surprised to find out that pattern matching doesn't work in arg lists: Map<String Map<String, int>> mapOfMaps = ...;
mapOfMaps.entries.map(({String k: Map<String, int> v}) => ...); (Yes, I know I can just do |
@benthillerkus on an unrelated sidenote on that example, there is |
@munificent In Dart we can do this: fn(data) {
final (
:int a,
:String b,
) = data;
print('$a, $b');
} but not this: fn((
:int a,
:String b,
)){
print('$a, $b');
} I don't see why this would interfere with [] and {}. It's just addition. |
I strongly agree that Dart would be greatly improved by being able to destructure records in lambda parameters. In the meantime, here's a workaround we use for at least simple record types:
Usage:
Hope this might be useful to others. The pattern supports more boilerplate (eg. |
Looked for an issue on this, but did not find one. This was briefly mentioned in #2774:
In Rust, you can do:
This sort of syntax would be very nice to have in Dart, like:
The text was updated successfully, but these errors were encountered: