-
Notifications
You must be signed in to change notification settings - Fork 222
Description
We're working on primary constructors. Among many nice things about this feature is that it eliminates the verbosity of repeating the entire class name when writing a constructor, which may sometimes be quite long:
// Today:
class SomeEmbarrassinglyLongClassNameWhy {
SomeEmbarrassinglyLongClassNameWhy() {
print('Phew!');
}
}
// Using an in-body declaring constructor:
class SomeEmbarrassinglyLongClassNameWhy {
this() {
print('Phew!');
}
}
This is nice, but since a class can only have one in-body declaring constructor and it must be generative, it's of limited help for classes with multiple constructors or factory constructors.
I think there is general sentiment on the language team to come up with a shorter notation for all constructor declarations. We've discussed it informally but I don't think there's a tracking issue. Now there is. :)
A couple of options:
Use this
instead of the class name
Generalizing from in-body declaring constructors, we can use this
for all constructors:
Current syntax Proposed
----------------------------------------- -------------------
LongClassName() {} this() {}
LongClassName.name() {} this.name() {}
const LongClassName() {} const this() {}
const LongClassName.name() {} const this.name() {}
LongClassName(): this.other(); this(): this.other();
LongClassName.name(): this(); this.name(): this();
const LongClassName(): this.other(); const this(): this.other();
const LongClassName.name(): this(); const this.name(): this();
factory LongClassName() { ... } factory this() { ... }
factory LongClassName.name() { ... } factory this.name() { ... }
factory LongClassName() = D; factory this() = D;
factory LongClassName.name() = D; factory this.name() = D;
const factory LongClassName() = D; const factory this() = D;
const factory LongClassName.name() = D; const factory this.name() = D;
Literally just replace the class name with this
in all constructors. This syntax makes generative constructors ambiguous with an in-body declaring constructor. I believe that's fine. An in-body declaring constructor with no field parameters is semantically identical to a generative constructor. So when the syntax is fully ambiguous, the semantics are the same so the distinction doesn't matter.
If a constructor has any field parameters, then their presence implies that the constructor is unambiguously a declaring one.
Put another away, with this syntax, we'd say that the definition of an in-body declaring constructor is a constructor that has at least one field parameter.
Use new
instead of the class name
We could keep this
for declaring/primary constructors and use new
in place of the class name for all other constructors:
Current syntax Proposed
----------------------------------------- -------------------
LongClassName() {} new() {}
LongClassName.name() {} new.name() {}
const LongClassName() {} const new() {}
const LongClassName.name() {} const new.name() {}
LongClassName(): this.other(); new(): this.other();
LongClassName.name(): this(); new.name(): this();
const LongClassName(): this.other(); const new(): this.other();
const LongClassName.name(): this(); const new.name(): this();
factory LongClassName() { ... } factory new() { ... }
factory LongClassName.name() { ... } factory new.name() { ... }
factory LongClassName() = D; factory new() = D;
factory LongClassName.name() = D; factory new.name() = D;
const factory LongClassName() = D; const factory new() = D;
const factory LongClassName.name() = D; const factory new.name() = D;
This has the advantage that you can recognize a declaring constructor at a glance since it will be the only one that starts with this
.
It has the disadvantages of containing const new
and factory new
, which may send confusing conflicting signals to readers.
Use new
with some other tweaks
If const new
and factory new
are confusing, we could tweak the syntax in some combinations to avoid those. Here's one way:
Current syntax Proposed
----------------------------------------- -------------------
LongClassName() {} new() {}
LongClassName.name() {} new.name() {}
const LongClassName() {} const() {}
const LongClassName.name() {} const.name() {}
LongClassName(): this.other(); new(): this.other();
LongClassName.name(): this(); new.name(): this();
const LongClassName(): this.other(); const(): this.other();
const LongClassName.name(): this(); const.name(): this();
factory LongClassName() { ... } factory() { ... }
factory LongClassName.name() { ... } factory.name() { ... }
factory LongClassName() = D; factory() = D;
factory LongClassName.name() = D; factory.name() = D;
const factory LongClassName() = D; const factory() = D;
const factory LongClassName.name() = D; const factory.name() = D;
This simply removes new
constructors that already have const
or factory
. It's the shortest of all three proposals.
It is technically breaking because we would have to treat factory
more like a reserved word to do this. Currently, factory() { ... }
is valid syntax for an instance method named factory
.
Opinion
Personally, I lean towards the first proposal. I like the idea that it means this
is uniformly the keyword for "produce a new instance" without stepping into the distinction between const/non-const and generative/factory. It makes moving a constructor from declaring to non-declaring a little more seamless because you don't have to touch a leading keyword.