language
language copied to clipboard
Named arguments
Named argument
As opposed to named parameters, named arguments is about using the parameter name on the call site.
Named arguments enable you to specify an argument for a positional parameter by matching the argument with its name rather than with its position in the parameter list.
Example:
void main() {
final a = A(x: 1, y: 2);
final another = A(y: 2, x:1);
}
class A {
final int x;
final int y;
A(this.x, this.y);
}
Rationale:
The decision to use named or positional arguments can be a decision the call site should make.
Private properties
void main() {
final a = A(x: 1, y: 2);
}
class A {
final int _x;
final int _y;
A(this._x, this._y);
}
This could lead to other beneficial features down the line like:
Declaring all fields in a constructor
class A {
final int x;
final int y;
final int z;
A(this.*);
}
Related: Object spread shorthand
Syntax sugar ...Object is used in a constructor / function call to unpack labels:
void main() {
final a = A(x: 1, y: 2);
final b = B(...a, z: 3);
// equivalent to
final bWithoutSugar = B(x: a.x, y: a.y, z: 3);
}
class A {
final int x;
final int y;
A(this.x, this.y);
}
class B {
final int x;
final int y;
final int z;
A(this.x, this.y, this.z);
...Object unpack the labels with the intersection between the parameters name and the object getters name.
Copies with null values
The last declaration of the field wins, allowing copying with null values (when the fields are not private).
void main() {
final a = A(x: 1, y: 2);
final another = A(...a, y: null);
}
class A {
final int x;
final int? y;
A(this.x, this.y);
}
I'm sure I have proposed something like this before, possibly as part of some other feature (I can't find an issue right now).
It's a nice idea which allows users to refer to parameters by name, when they have a name, even if they are not named parameters.
The risks are that the names are not really part of the function value, they're just metadata on the static function types.
- You can't use those names in a dynamic invocation.
- Any operation on types may affect the metadata. We'll have to specify precisely how it's propagated through all type operations (with Up and Down being the biggest risks, and Norm probably not mattering since it's only used at runtime).
- It becomes a breaking change to change the name of a positional parameter. Even if you never intended it to be used as a parameter name in that way, there is no way to opt out. (Well, you can make it a private name, but that's ugly, and we don't want everybody making their positional parameters private just to not get trapped with a name that they want to change, effectively getting trapped with an ugly private name instead.)
(Well, you can make it a private name, but that's ugly, and we don't want everybody making their positional parameters private just to not get trapped with a name that they want to change, effectively getting trapped with an ugly private name instead.)
In what I envisioned here
- named parameters are removed, I don't see the point, it's also a breaking change to rename those.
- all params can be used as named arguments, you can't opt out.
Is it that bad to have parameters name part of the public contract when compared with the potential benefits ?
You can't use those names in a dynamic invocation.
The dynamic issue seems like a non issue to me. Dynamic usages are pretty seldom and if you really need to label, you can cast.
- It becomes a breaking change to change the name of a positional parameter. Even if you never intended it to be used as a parameter name in that way, there is no way to opt out.
Python here has positional only args:
def foo(bar: str, /): ...
If we decide to have nullable args / args with default as optional, we can reuse [...] here
I'm sure I have proposed something like this before, possibly as part of some other feature (I can't find an issue right now).
This is basically what my "Enhanced Normal Parameters" strawman is. I haven't written it up in public form yet, but maybe I should.
It's how most other languages with named arguments work. There are some real trade-offs with it but I suspect that overall it's a better approach. Certainly it would make parameter list syntax cleaner and simpler.
@munificent is it going to happen in the future altogether with: https://github.com/dart-lang/language/issues/2232? Lack of named arguments by default and treating optional only by passing [] and {} in signatures is why Dart is for me unnecessary verbose..
Python approach here to treat specially only positional-only and keyword-only args is IMO much better approach.
With these 2 approaches, [] and {} could be reused only for positional-only / keywords-only
@munificent is it going to happen in the future altogether with: #2232?
Predicting the future is hard. :) We know we want to make progress on brevity in the language but we aren't committed yet to how.
@munificent is it going to happen in the future altogether with: #2232?
Predicting the future is hard. :) We know we want to make progress on brevity in the language but we aren't committed yet to how.
IMO Kotlin-like syntax with Dart backend would be step in the right direction towards both elegant and powerful language ;)
@munificent I'm interested in reading your proposal
This implicit name proposal made me think of this again.
Today I can change foo(int x, int y) into foo(int y, int x) which could be a breaking change unenforced by the compiler. This is a bit of a stretch but if there was "implicit names" without the leading :, and named arguments, then this would not be a breaking change for people calling foo(x, y), since that's reordered automatically.
On a side note: I still don't understand why, you would support both named argument and named parameters at the same time. They overlap in purpose: both exist for call-site clarity.