-
Notifications
You must be signed in to change notification settings - Fork 214
Abbreviated formal parameter lists using kwargs #58
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
After spending some time thinking about this, I have some thoughts that I'd like to share: First, since Dart is closer to JavaScript than it is to Python, I think a better syntax would be Second, using this approach (as opposed to a
// Instead of this (which is not very useful):
abstract class A {
void f({int x});
forward g({String y}) = f;
}
// You could do this:
abstract class A {
void f({int x});
void g({String y, ...rest}) {
// do my own thing using `y`...
f({...rest});
// continue doing stuff with `y`...
}
}
abstract class A {
void f({int x});
// At first sight, it feels like we forwarding `y` to `f`.
forward g({String y}) = f;
}
abstract class A {
void f({int x});
void g({String y, ...rest}) => f({...rest});
} There are few things to sort out in order to make this work:
void f(int x, int y) { ... }
void g(...rest) => f(...rest); // positional parameters.
void f({int x, int y}) { ... }
void g({...rest}) => f({...rest}); // named parameters.
void f(int x, {int y}) { ... }
void g(...positional, {...named}) => f(...positional, {...named}); // allow both?
void f({int x, int y}) { ... }
void g({int x, int y}) { ... }
void h({int x}) { ... }
void k({String s}) { ... }
void foo({ int z, ...rest}) {
f({...rest}); // Ok
g({...rest}); // Ok
h({...rest}); // Should we allow this and only pass `x` here?
k({...rest}); // Error: incompatible parameter lists.
}
void f({int x, int y}) { ... }
void g({int x, ...rest}) {
// Do something using `x`.
f({x: x, ...rest}); // Inference needs to know that `...rest` only contains `y` but not `x.
} |
What happens when |
It should do what you'd expect it to do: void f({int x, int y = 1}) => print('$x:$y');
void g({int x, int y = 2}) => print('$x:$y');
void foo({...rest}) {
f({...rest});
g({...rest});
}
void main() {
foo(x: 5);
// "5:1"
// "5:2"
foo(x: 5, y: 6);
// "5:6"
// "5:6"
} When you do But when I tried the following on dartpad: void f({int x, int y = 1}) => print('$x:$y');
void foo({int x, int y}) {
bar(x: x, y: y);
}
void main() {
foo(x: 5);
// "5:null"
} So I can understand how the semantics I described for |
Although, I would argue that in the dartpad example, the risk is that But in the |
If we also have some way to express the types this could bring us a long way towards solving #157 |
@tatumizer I'm ok if it throws an exception or prints something like |
With null-safety, not passing an argument y would not be optional and null is not an option unless y is nullable and not required, so this could make the named parameter y 'required' if the functions called do not have the same default. And you probably want some sort of override syntax in case you want to specify a new default. // y is a required named parameter because the defaults don't agree
void foo({...rest}) {
f({...rest});
g({...rest});
}
// give y a new default
// anything that comes after a rest parameter is an override and
// * statically an error if y is not needed in f / g signatures
// * when ...rest desugars, it replaces the y from the rest parameter
void foo({...rest, int y=10}) { // or void foo({..rest; int y = 10})
f({...rest});
g({...rest});
} Named tuples and destructuring tuples into method arguments is essentially how I see this issue. Essentially rest is a tuple type with the type of the combined parameter signature. The This would be so nice! However the problem is: void f({int x, int y = 1}) => print('$x:$y');
void g({int x, String y = ''}) => print('$x:$y');
void foo({...rest}) {
f({...rest});
g({...rest});
} What is the type of rest? |
Also |
And can it work with |
In response to the topic filed as request #57, Mouad Debbar mentioned that Python supports a special formal parameter declaration
**kwargs
, which would make it possible to achieve the following much shorter form of the example from #57:Considered purely as syntactic sugar, it would be possible for the analyzer and compilers to expand
**kwards
into the actual list of named arguments, which would make it easy to proceed with the standard static analysis of both declarations and corresponding call sites using the rules we have today. It would then be possible to let**kwargs
stand for a set of named formal parameter declarations on one side of the:
, and passing those named parameters on to parameters with the same name on the other side.The text was updated successfully, but these errors were encountered: