Reputation: 51133
Given two Maybe
values, how can I combine them into a single Maybe
that will either:
onSuccess()
whenever either of the source Maybes
calls onSuccess
onComplete()
whenever both of the source Maybes
call onComplete()
?(Cf. Option.orElse()
in Scala or Vavr.)
E.g., assuming the existence of a combine()
method that does what I want:
combine(Maybe.just(a), Maybe.empty()) ≍ Maybe.just(a)
combine(Maybe.empty(), Maybe.just(b)) ≍ Maybe.just(b)
combine(Maybe.empty(), Maybe.empty()) ≍ Maybe.empty()
combine(Maybe.never(), /*anything*/ ) ≍ /*the thing*/
combine(/*anything*/, Maybe.never()) ≍ /*the thing*/
At first I thought amb()
& family were what I was looking for, but that completes as soon as either source Maybe
completes, meaning if the first Maybe
completes without a value, you never get the value from the second Maybe
.
Right now I'm using
Maybe.mergeArray(m1, m2).firstElement()
which seems to do what I want, but I’m not certain it’s correct and I’m not certain it’s the cleanest way to do it. (For instance, if there’s some delay, will it call onSuccess()
immediately when one or the other source does, or will it wait for both onComplete()
s?)
Is this correct? Is there a more idiomatic approach?
ETA: I'm happy taking the first value; I don't need to wait for both to complete:
combine(Maybe.just(a), Maybe.just(b)) ≍ Maybe.just(/* a or b, don't care */)
(I can imagine situations in which I might prefer one or the other and want to indicate that by order of the arguments, but in that situation I suspect sequential would be better than parallel.)
Upvotes: 4
Views: 1497
Reputation: 39853
There's a slightly different approach which might be a little nearer to your definition. This would be using Observable.switchMapMaybe()
:
Maps the upstream items into
MaybeSources
and switches (subscribes) to the newer ones while disposing the older ones (and ignoring their signals) and emits the latest success value of the current one if available while failing immediately if this Observable or any of the active innerMaybeSources
fail.
Observable.just(m1, m2).switchMapMaybe(m -> m).firstElement()
But the approach using Maybe.mergeArray(m1, m2).firstElement()
should be sufficient as well. The firstElement()
operator emits the first element emitted by the mergeArray()
flowable. This one is unordered and thus there's no information about the completion of any of the maybes.
Upvotes: 1