-
Notifications
You must be signed in to change notification settings - Fork 214
Future.wait casting is not solved by Records #2303
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
If (when!) we don't allow abstracting over pattern width, you can't get a single typed HOWEVER (use all the emphasis!), we can decide to change the That's actually a generalization of Should it work only for an expression with a static record type, or can it also work on We'd have to define the behavior in case any component future completes with an error. @munificent Do this! We want that to be the behavior from the start, it's hard to add later, if |
Can we also do that for lists too, so that awaiting a list of futures yields a future of a list of the results? Sometimes you do need to wait for a dynamically-sized homogeneous list of asynchronous tasks. (I suppose the answer is "no" because there could be some user-defined class that implements both Yes, I'm on board with this. Maybe we should carve it out as a separate proposal since the main patterns one already has a lot of surface area? |
Barring that, you could do something fairly nice with extensions: extension FutureRecord2Extension<T1, T2> on (Future<T1>, Future<T2>) {
Future<(T1, T2)> wait() async {
var (f1, f2) = this;
var [e1 as T1, e2 as T2] = await Future.wait([f1, f2]);
return (e1, e2);
}
}
extension FutureRecord3Extension<T1, T2, T3> on (Future<T1>, Future<T2>, Future<T3>) {
Future<(T1, T2, T3)> wait() async {
var (f1, f2, f3) = this;
var [e1 as T1, e2 as T2, e3 as T3] = await Future.wait([f1, f2, f3]);
return (e1, e2, e3);
}
}
// Other arities...
Future<int> asyncThing() ...
Future<String> another() ...
main() async {
var (n, s) = await (asyncThing(), another()).wait();
} |
Like the extensions, hate the dynamic typing being necessary. Also doesn't scale well with named record elements. A more direct approach, without using extension FR2X<T1, T2> on (Future<T1>, Future<T2>) {
Future<(T1, T2)> wait() async {
Completer<(T1, T2)> c = Completer.sync();
T1? v1;
T2? v2;
var count = 0;
List<AsyncError>? errors;
void tryComplete() {
if (++count == 2) {
if (errors == null) {
c.complete((v1 as T1, v2 as T2));
} else {
c.completeError(AwaitRecordException<(T1?, T2?)>((v1, v2), errors));
}
}
}
var (f1, f2) = this;
unawaited(f1.then((v) { v1 = v; tryComplete()}, onError: (Object e, StackTrace s) {
(errors ??= []).add(AsyncError(e, s); tryComplete();
}));
unawaited(f2.then((v) { v2 = v; tryComplete()}, onError: (Object e, StackTrace s) {
(errors ??= []).add(AsyncError(e, s); tryComplete();
}));
return c.future;
}
} Doesn't scale to other record structures any better. This really begs to be a language or library feature, and for best typing, it really should be a language feature. |
I'd like to re-surface this. I think this proposal has a lot of potential value, and I think if we're going to do it, we need to do it now (since once the first record gets awaited, this becomes a breaking change). Thoughts on this? cc @munificent @lrhn @eernstg @jakemac53 @natebosch @stereotype441 |
Closing this as a duplicate of #2321 since that has covers the same territory and has more details. |
Thanks for all of the discussion! |
One of the five paragraphs under Motivation is about
Future.wait
:https://github.com/dart-lang/language/blob/df9574472a7a84aa518b88794c5ec9ff6349f170/working/0546-patterns/records-feature-specification.md
As far as I can tell, Records cannot solve this for the existing generic
Future.wait
. There is not a new signature we can use forFuture.wait
that would return a record, for example. (You could define a niceFuture<(T0, T1)> wait2(Future<T0> f0, Future<T1> f1)
,wait3
,wait4
, etc. though.)It looks to me like this is more directly solved with the cast binder pattern:
Not sure what the AI is here; perhaps the motivating example could be moved to the "cast binder" pattern section...
The text was updated successfully, but these errors were encountered: