Skip to content
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

Infer return types of Future.wait independently? #2838

Closed
rubenferreira97 opened this issue Feb 10, 2023 · 3 comments
Closed

Infer return types of Future.wait independently? #2838

rubenferreira97 opened this issue Feb 10, 2023 · 3 comments
Labels
request Requests to resolve a particular developer problem

Comments

@rubenferreira97
Copy link

rubenferreira97 commented Feb 10, 2023

With records coming to dart, would be possible to define a way to infer each type separately?

void main() async {
  final record = (Future.value(1), Future.value("String"), Future.value(true));
  final result = waitRecord(record); // should infer (int, String, bool)
}

T/*(RecordWithResolvedFutures<T>)*/ waitRecord<T extends Record/*(WithOnlyFutures)*/>(T b) {
  // resolve Futures
  return b; 
}

RecordWithOnlyFutures and RecordWithResolvedFutures<T extends RecordWithOnlyFutures> are just a placeholders for a internal solution.

To be honest, I really don't know if this is possible to implement, since it seems a little hard to represent this type, but is a step forward to a safer typing. I really hate to cast different future types like this:

final aInt = result[0] as int;
final aString = result[1] as String;
final aBool = result[2] as bool;
@rubenferreira97 rubenferreira97 added the request Requests to resolve a particular developer problem label Feb 10, 2023
@mateusfccp
Copy link
Contributor

mateusfccp commented Feb 10, 2023

Seems related to #2321, in which they decided against making something language-specific for waiting records.

In this issue, @lrhn left an example of an extension that does something similar, so that you may call:

(futureA, futureB, futureC).wait;

@rubenferreira97
Copy link
Author

rubenferreira97 commented Feb 10, 2023

Thank you, that seems what I was looking for! If I understood correctly that extension would be available on SDK/core level right? If yes does anybody knows if is it already available on dart 3 (master) so I can experiment it?

@lrhn
Copy link
Member

lrhn commented Feb 10, 2023

I'm not sure it's entirely decided whether the extension goes into the SDK or into package:async. I'd prefer the former.
It's not landed yet, or completed.

Here's a quick version to play with.

import "dart:async";

extension FutureRecordWait3<R, S, T> on (Future<R>, Future<S>, Future<T>) {
  /// Process futures in parallel.
  ///
  /// If any of the futures throw,
  /// the returned future throws a [ParallelAwaitError],
  /// with a `(R?, S?, T?)` containing the successful values or null,
  /// and an `(AsyncError?, AsyncError?, AsyncError?)` containing
  /// the error results or `null`.
  Future<(R, S, T)> operator ~() {
     var result = Completer<(R, S, T)>.sync();
     R? v1; 
     AsyncError? e1;
     S? v2;
     AsyncError? e2;
     T? v3;
     AsyncError? e3;
     var waiting = 3;
     void onDone() {
       if (--waiting == 0) {
         if (e1 == null && e2 == null && e3 == null) {
           result.complete((v1 as R, v2 as S, v3 as T));
         } else {
           result.completeError(ParallelWaitError<
               (R?, S?, T?), (AsyncError?, AsyncError?, AsyncError?)>(
               (v1, v2, v3), (e1, e2, e3)));
         }
       }
     }
     $1.then((v) {
       v1 = v;
       onDone();
     }, onError: (e, s) {
       e1 = AsyncError(e, s);
       onDone();
     }); 
     $2.then((v) {
       v2 = v;
       onDone();
     }, onError :(e, s) {
       e2 = AsyncError(e, s);
       onDone();
     }); 
     $3.then((v) {
       v3 = v;
       onDone();
     }, onError: (e, s) {
       e3 = AsyncError(e, s);
       onDone();
     }); 
     return result.future;
  }
}
             
             
class ParallelWaitError<V extends Record, E extends Record>   
           extends Error {
  final V values;
  final E errors;
  ParallelWaitError(this.values, this.errors);
}             

which you can use like:

void main() async {
  var v = await ~(Future.value(1), Future.value("a"), Future.value(false));
  // v has type (int, String, bool)
}

(The real code will have some abstractions to help with avoiding the code repetition.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests

3 participants