-
Notifications
You must be signed in to change notification settings - Fork 213
Provide an expression to maybe provide an optional parameter #1401
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
Might be interesting to have a keyword that means "insert whatever value the receiver would use as a default here if we didn't say anything". |
And on second thought staying with the default if the expression evaluates to void foo([int? bar = 0]) {}; |
Yeah, null already means something different, so it'd be a pretty significant breaking change to make "null" mean "use the default" here. |
What about the following instead? class Sample {
const Sample({int? a}): a = a ?? 42;
final int a;
} We could have a shorthand for this: class Sample {
const Sample({this.a ??= 42});
final int a;
} |
@rrousselGit Your suggestion only works for the case where the actual parameter is non-nullable, because otherwise how to know whether nothing was given or null was given? One other downside of this (as this is already a possible workaround now) is that you will no longer see the default from outside the function (that could be omitted with your second suggestion I guess. @Hixie's suggestion seems more attractive to me as this might increase the expressiveness of the language overall (perhaps there are other cases where this can become relevant 🤔) |
The problem with "insert whatever value the receiver would use as a default here if we didn't say anything" is that's not the default behaviour when using composition Take the following code as example: class SomeWidget extends StatelessWidget {
SomeWidget({this.a = 42});
final int? a;
...
}
class ComposedWidget extends StatelessWidget {
ComposedWidget({this.a});
final int? a;
@override
Widget build(BuildContext context) {
return SomeWidget(a: a);
}
} Then, when writing This is a common mistake that developers make. To work around that, in my projects I've stopped using default values and null entirely, in favour of TextField({ Option<int>? maxLines }): maxLines = maxLines ?? const Option(1);
final Option<int> maxLines This covers all the cases and avoid mistakes. As for documentation, the dartdoc can mention what the default value is. |
I might be mixing up syntax and semantics now, but if there was a keyword meaning nothing given this might be useful in other occasions and supports what @tatumizer proposes by foo(giveValue ? (x: value) : newKeyWord) {};
// but I guess "x:value" is not actually something an expression can return so this syntax might not make sense |
I'd be pretty happy with this solution. The distinction between "null" and "no value" is still pretty subtle, like how javascript settled on undefined, which I personally consider pretty bad. The idea of |
The usual issues come up with this: foo([int x = -1, int y = -1]) => ...;
...
int? x = ..., y = ...;
foo(x ?? default, y ?? default) Here we pass either the value of I'm fairly sure there is code out there which would be very surprised by getting a default value for the first argument and a non-default for the second. Example: int hash([Object o1 = _sentinel, Object o2 = _sentinel, Object o3 = _sentinel, ...) {
if (identical(_sentinel, o1)) return 0;
if (identical(_sentinel, o2)) return o1.hashCode;
if (identical(_sentinel, o3)) return hash2(o1, o2);
// ...
} Here, the sentinel is a value that you can be sure is not passed as an explicit argument, and since you cannot pass a later positional argument without passing all the ones before, it doesn't have to check ahead and see whether That kind of code would break with this change. (That said, I'd be all for allowing you to omit earlier optional parameters already, like |
Then my messaging is right on point. 😁 I worry that a feature only for parameters might be too specific. If there are other places where "nothing" makes sense (like in a list literal), would it be better to have the same syntax? If we go with |
Absolutely not natural, no. The difference between a list (an arbitrary-length sequence of values of the same type) and an argument list (a fixed-length sequence of values of different types) means that omitting an entry at run-time means completely different things. In a list literal, omitting an element at any point just makes the list shorter, and moves all later element up by one position. In an argument list, physically omitting an entry moves all later arguments up by one position, which may change the required type. So, "omitting" in an argument list cannot mean the same thing as in a list literal. It must mean (if it exists at all) that that argument is not passed, but later arguments retain their position. |
In API and language design, we try to avoid having the same words mean different things. We don't always succeed. The question here is then how similar (I'd allow you to write Alternatively, allow |
A pretty simple (yet hard) way to deal with this would be to go the javascript way: another sentinel value, apart from in javascript, passing |
Using |
Why can't we keep it simple with existing null aware operators?? |
As discussed on Discord there is no short solution to apply an optional parameter maybe a value using an expression:
The same issue should apply for optional positional parameters.
Did not have the time yet to fully read on the Pattern language feature draft, but I can imagine that there might be some ”connection“ in the long run.
The text was updated successfully, but these errors were encountered: