-
Notifications
You must be signed in to change notification settings - Fork 227
Description
There is a longstanding desire to have better syntax for casts that appear inline in a method chain:
((a as Whatsit).frobIt(3) as Whosit).fizzle();If we move ahead with #192 there is also a desire to have a short syntax for implicitly casting to the context type (see for example the hand-rolled cast function used in this cl removing implicit casts).
It seems likely that we can solve both of these with a single piece of syntax. For example, we could add a postfix cast operator !! which casts to the context type, also usable in the form !!<T> which casts to T. Code that formerly used an implicit cast:
takeList(List<int> f) {}
Iterable<int> mkIterable() {}
void test() {
takeList(mkIterable());
}could be rewritten as follows:
takeList(List<int> f) {}
Iterable<int> mkIterable() {}
void test() {
takeList(mkIterable()!!);
}And the example from above with inline casts could be written more cleanly as well:
a!!<Whatsit>.frobIt(3)!!<Whosit>.fizzle();We might wish to specify it to be an error to use !! to perform a side cast when the type is not explicitly written.
An alternative syntax which would be more consistent with existing Dart code would be to use .as and .as<T>.
takeList(List<int> f) {}
Iterable<int> mkIterable() {}
void test() {
takeList(mkIterable().as);
} a.as<Whatsit>.frobIt(3).as<Whosit>.fizzle();Unfortunately this would be a breaking change, since as is not a reserved word in Dart. In practice this is likely non-breaking, @munificent is proposing to scrape some code to verify this.
If we had extension methods + generic getters, we could specify this as a generic extension method:
extension Cast on Object {
T get as<T> => this as T;
}This doesn't capture a side cast restriction, but it may avoid the breaking change issue. It seems unlikely that we will have both of these features in place in a suitable time frame to use this encoding though.
Other ideas for syntax that have been put out for consideration:
x.(as T)and something likex.(as)orx.(as _)- this could possibly be a use of two general mechanisms:
- a way of using an operator in a postfix position
- enabling
await a->a.await,a + b->a.+(b), possibly alsofoo(x, y)->x.foo(y)
- a prefix version of our existing cast operator
- enabling
- a way of using an operator in a postfix position
x.cast<T>- This is probably not feasible, since we have
castmethods on various core library types.
- This is probably not feasible, since we have