public static <A, B, C> PromiseWithoutUpdates<C> lift(
      final Lambda2<A, B, C> f, PromiseWithoutUpdates<A> pa, PromiseWithoutUpdates<B> pb) {
    return Transaction.run(
        () -> {
          class Tuple {
            Tuple(Optional<A> oa, Optional<B> ob) {
              this.oa = oa;
              this.ob = ob;
            }

            Optional<A> oa;
            Optional<B> ob;
          };
          Lambda2<Tuple, Tuple, Tuple> combine =
              (l, r) -> new Tuple(l.oa.isPresent() ? l.oa : r.oa, l.ob.isPresent() ? l.ob : r.ob);
          Lambda1<Tuple, Optional<C>> result =
              t ->
                  t.oa.isPresent() && t.ob.isPresent()
                      ? Optional.of(f.apply(t.oa.get(), t.ob.get()))
                      : Optional.empty();
          Stream<Tuple> sA = pa.sDeliver.map(a -> new Tuple(Optional.of(a), Optional.empty()));
          Cell<Tuple> vA = pa.oValue.map(oa -> new Tuple(oa, Optional.empty()));
          Stream<Tuple> sB = pb.sDeliver.map(b -> new Tuple(Optional.empty(), Optional.of(b)));
          Cell<Tuple> vB = pb.oValue.map(ob -> new Tuple(Optional.empty(), ob));
          Stream<Tuple> sAArrives = sA.snapshot(vB, combine);
          Stream<Tuple> sBArrives = sB.snapshot(vA, combine);
          Stream<Tuple> sSimultaneous = sA.merge(sB, combine);
          Stream<C> sDeliver =
              Stream.filterOptional(sAArrives.orElse(sBArrives).orElse(sSimultaneous).map(result))
                  .once();
          Cell<Optional<C>> oValue = Cell.lift(combine, vA, vB).map(result);
          return new PromiseWithoutUpdates<C>(sDeliver, oValue);
        });
  }
Beispiel #2
0
 static <A> Cell<List<A>> sequence(Collection<Cell<A>> in) {
   Cell<List<A>> out = new Cell<>(new ArrayList<A>());
   for (Cell<A> c : in)
     out =
         Cell.lift(
             (l0, a) -> {
               List<A> l = new ArrayList<A>(l0);
               l.add(a);
               return l;
             },
             out,
             c);
   return out;
 }