Skip to content

Instantly share code, notes, and snippets.

@yongjhih
Last active June 7, 2024 03:18
Show Gist options
  • Save yongjhih/89a199ec14127f92a001d2e15e8a32ac to your computer and use it in GitHub Desktop.
Save yongjhih/89a199ec14127f92a001d2e15e8a32ac to your computer and use it in GitHub Desktop.
/// For dart 2:
///
/// ```
/// import 'package:tuple/tuple.dart';
///
/// Future<Tuple2<T1, T2>> zipAsync<T1, T2>(
/// Future<T1> future1, Future<T2> future2) async {
/// late T1 result1;
/// late T2 result2;
///
/// await Future.wait([
/// future1.then((value) => result1 = value),
/// future2.then((value) => result2 = value)
/// ]);
///
/// return Tuple2(result1, result2);
/// }
/// ```
///
/// Usage:
///
/// ```
/// final (a, b) = await zipAsync(
/// 1.seconds.delayed(),
/// 2.seconds.delayed(),
/// );
/// ```
///
/// Usage: For 3 futures:
///
/// ```
/// final (a, (b, c)) = await zipAsync(
/// 1.seconds.delayed(),
/// zipAsync(
/// 2.seconds.delayed(),
/// 3.seconds.delayed(),
/// ),
/// );
/// ```
///
/// Usage: For 3+ futures:
///
/// ```
/// final (a, (b, (c, (d, (e, (f, g)))))) = await zipAsync(
/// 1.seconds.delayed(),
/// zipAsync(
/// 2.seconds.delayed(),
/// zipAsync(
/// 3.seconds.delayed(),
/// zipAsync(
/// 4.seconds.delayed(),
/// zipAsync(
/// 5.seconds.delayed(),
/// zipAsync(
/// 6.seconds.delayed(),
/// 7.seconds.delayed(),
/// ),
/// ),
/// ),
/// ),
/// ),
/// );
/// ```
Future<(T1, T2)> zipAsync<T1, T2>(
Future<T1> future1,
Future<T2> future2,
) async {
late T1 result1;
late T2 result2;
await Future.wait([
future1.then((value) => result1 = value),
future2.then((value) => result2 = value)
]);
return (result1, result2);
}
extension FutureZipX<T> on Future<T> {
/// ```
/// test("zip", () async {
/// final (a, b) = await Future.value(1).zip(Future.value(2));
/// expect(a, 1);
/// expect(b, 2);
/// });
/// ```
/// ```
/// test("zip3", () async {
/// final (a, b, c) = await Future.value(1)
/// .zip(Future.value(2))
/// .zip(Future.value(3));
/// expect(a, 1);
/// expect(b, 2);
/// expect(c, 3);
/// });
/// ```
Future<(T, T2)> zip<T2>(Future<T2> future2) => zipAsync(this, future2);
/// ```
/// test("zipWith3", () async {
/// final ((a, b), c) = await Future.value(1)
/// .zipWith(Future.value(2))
/// .zipWith(Future.value(3));
/// expect(a, 1);
/// expect(b, 2);
/// expect(c, 3);
/// });
/// ```
Future<(T, T2)> zipWith<T2>(Future<T2> future2) => zipAsync(this, future2);
}
extension FutureZip2X<T1, T2> on Future<(T1, T2)> {
/// test("zipFlatten", () async {
/// final (a, b, c) = await Future.value(1)
/// .zip(Future.value(2))
/// .zip(Future.value(3));
/// expect(a, 1);
/// expect(b, 2);
/// expect(c, 3);
/// });
Future<(T1, T2, T3)> zip<T3>(Future<T3> future2) async =>
(await zipAsync(this, future2)).flatten();
}
extension FutureZip3X<T1, T2, T3> on Future<(T1, T2, T3)> {
Future<(T1, T2, T3, T4)> zip<T4>(Future<T4> future2) async =>
(await zipAsync(this, future2)).flatten();
}
extension FutureZip4X<T1, T2, T3, T4> on Future<(T1, T2, T3, T4)> {
Future<(T1, T2, T3, T4, T5)> zip<T5>(Future<T5> future2) async =>
(await zipAsync(this, future2)).flatten();
}
/// ```
/// test("zip.flatten", () async {
/// final (a, b, c) = await Future.value(1)
/// .zip(Future.value("2"))
/// .zip(Future.value(3.0))
/// .flatten();
/// expect(a, 1);
/// expect(b, "2");
/// expect(c, 3.0);
/// });
/// ```
extension FutureTuple3X<T1, T2, T3> on Future<((T1, T2), T3)> {
Future<(T1, T2, T3)> flatten() async {
final ((a, b), c) = await this;
return (a, b, c);
}
}
/// ```
/// test("zip.flatten", () async {
/// final (a, b, c, d) = await Future.value(1)
/// .zipWith(Future.value("2"))
/// .zipWith(Future.value(3.0))
/// .flatten()
/// .zipWith(Future.value(true))
/// .flatten();
/// expect(a, 1);
/// expect(b, "2");
/// expect(c, 3.0);
/// expect(d, true);
/// });
/// ```
extension FutureTuple4X<T1, T2, T3, T4> on Future<((T1, T2, T3), T4)> {
Future<(T1, T2, T3, T4)> flatten() async {
final ((a, b, c), d) = await this;
return (a, b, c, d);
}
}
extension FutureTuple5X<T1, T2, T3, T4, T5> on Future<((T1, T2, T3, T4), T5)> {
Future<(T1, T2, T3, T4, T5)> flatten() async {
final ((a, b, c, d), e) = await this;
return (a, b, c, d, e);
}
}
extension Tuple2X<T1, T2, T3> on ((T1, T2), T3) {
(T1, T2, T3) flatten() {
final ((a, b), c) = this;
return (a, b, c);
}
}
extension Tuple3X<T1, T2, T3, T4> on ((T1, T2, T3), T4) {
(T1, T2, T3, T4) flatten() {
final ((a, b, c), d) = this;
return (a, b, c, d);
}
}
extension Tuple4X<T1, T2, T3, T4, T5> on ((T1, T2, T3, T4), T5) {
(T1, T2, T3, T4, T5) flatten() {
final ((a, b, c, d), e) = this;
return (a, b, c, d, e);
}
}
extension Tuple5X<T1, T2, T3, T4, T5, T6> on ((T1, T2, T3, T4, T5), T6) {
(T1, T2, T3, T4, T5, T6) flatten() {
final ((a, b, c, d, e), f) = this;
return (a, b, c, d, e, f);
}
}
extension Tuple6X<T1, T2, T3, T4, T5, T6, T7> on ((T1, T2, T3, T4, T5, T6), T7) {
(T1, T2, T3, T4, T5, T6, T7) flatten() {
final ((a, b, c, d, e, f), g) = this;
return (a, b, c, d, e, f, g);
}
}
extension Tuple7X<T1, T2, T3, T4, T5, T6, T7, T8> on ((T1, T2, T3, T4, T5, T6, T7), T8) {
(T1, T2, T3, T4, T5, T6, T7, T8) flatten() {
final ((a, b, c, d, e, f, g), h) = this;
return (a, b, c, d, e, f, g, h);
}
}
extension Tuple8X<T1, T2, T3, T4, T5, T6, T7, T8, T9> on ((T1, T2, T3, T4, T5, T6, T7, T8), T9) {
(T1, T2, T3, T4, T5, T6, T7, T8, T9) flatten() {
final ((a, b, c, d, e, f, g, h), i) = this;
return (a, b, c, d, e, f, g, h, i);
}
}
@nikitadol
Copy link

This may be convenient:

  test("zip.flatten", () async {
    final (a, b, c, d) = await Future.value(1)
        .zipWith(Future.value("2"))
        .zipWith(Future.value(3.0))
        .flatten()
        .zipWith(Future.value(true))
        .flatten();
    expect(a, 1);
    expect(b, "2");
    expect(c, 3.0);
    expect(d, true);
  });

But not for dart >= 3.0:

  test("dart native", () async {
    final (a, b, c, d) = await (
      Future.value(1),
      Future.value("2"),
      Future.value(3.0),
      Future.value(true)
    ).wait;
    expect(a, 1);
    expect(b, "2");
    expect(c, 3.0);
    expect(d, true);
  });

More here -> https://api.flutter.dev/flutter/dart-async/FutureRecord2.html (2-9)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment