Description
@munificent has a glorious write-up of declaring constructors: #4169
It allows var int x
as a parameter in declaring constructors, as a way to introduce a mutable instance variable. 🎉
The grammar allows 'var' <type> <identifier>
in every parameter, and the feature spec then disallows a var
+type from occurring in a non-declaring constructor using prose (it's a compile-time error if a parameter containing var
occurs in a non-declaring constructor parameter list).
I suggest we just allow it everywhere. It's easier than disallowing it, and the meaning is obvious. It makes var
and final
(finally) be symmetric.
It is unnecessary, because var int x
means the same as int x
, but var x
and x
also means the same thing in parameters, and we allow both.
One argument against is that if anyone does write var int x
as a normal parameter, someone else might initially read it as a field parameter, even though it's not a declaring constructor.
Most likley, nobody will write that. They don't write var x
today, even though it's valid. They don't write final int x
in parametes, even in code that insists on every local variable being final
if it can be.
I don't think we'll see an up-tick in occurrences of final int x
in normal parameters, or occurrences of var int x
at all, so the confusion risk should be minimal.
That also means that there is no benefit to allowing the syntax. (Hypothetically, allowing var int x
everywhere means that you can safely change any final
to var
in a variable declaration, without having to do anything else. Might be easier for code generators. But I don't expect users to just blindly replace final
with var
without looking at a declaration.)
It does mean that the same syntax means different things in different places, which is usually bad.
That's already the case for final int x
in declaring constructors, and this way, the issue would be symmetric in var
and final
. It'll be one less exception to remember, you can think of var
and final
as symmetric.
(Rather than: "You can use var int x
and final int x
in declaring constructors to declare a var
/final
field. In other parameters var int x
is an error. In other constructors final int x
means a final parameter.", it becomes "You can use (var|final) int x
in declaring constructors to declare a var
/final
field. In other parameters, (var|final) int x
just introduces a var/final parameter variable." It's symmetric, if you understand the difference between var
and final
, you can apply the consistenly, so I'd count this as a complexity score of 2 vs 3 when disallowing var int x
elsewhere. It all counts!)
It's only parameters, though, you can't actually declare a field as var int x;
. But you can write var (int x) = ...
. I'd be fine with allowing var int x;
for variables too.
(Allowing var int x;
may be a stepping stone to final
-by-default, if we ever want that. I do, don't know about "we".)
Options:
- Allow
var int x
as parameter everywhere. (My proposal.)- Go all in: Allow it in variable declarations too,
late var int x = 42;
. (Maybe, eventually.)
- Go all in: Allow it in variable declarations too,
- Disallow in parameters not in a declaring constructor. (Specified in feature spec.)
- Also, eventually, disallow
final
in non-declaring constructor parameters. (Suggested in feature spec.) - Or lint against it. (Suggested in feature spec.)
- Also, eventually, disallow
WDYT?
@dart-lang/language-team