I have a couple of Vavr Either's and I want to invoke a function with the Right
value for each of these Either's. For example:
Either<MyError, String> either1 = ..
Either<MyError, String> either2 = ..
Either<MyError, String> either3 = ..
Either<MyError, String>> methodRequiringAllInputs(String, String, String) {
..
}
I could of course do something like this:
either1.flatMap { value1 ->
either2.flatMap { value2 ->
either3.flatMap { value3 ->
methodRequiringAllInputs(value1, value2, value3);
}
}
}
But this is very ugly. In other languages you could just use something like do-notation or for comprehensions to flatten out the structure. I know that Vavr has the concept of a Validation which is an applicative functor that allows you to do:
Validation<MyError, String> validation1 = ..
Validation<MyError, String> validation2 = ..
Validation<MyError, String> validation3 = ..
Validation.combine(validation1, validation2, validation3)
.ap((validationValue1,validationValue2,validationValue3) -> .. );
which is much nicer.
My question is if something similar exists in Vavr for Either's to avoid the nested flatMap
structure? Note that I don't want to convert the Either
's to Validation
's.
By convention, Either's Left attribute represents a failure case and the Right one represents a success. However, based on our needs we can change this using projections – Either in Vavr is not biased towards Left or Right. If we project to Right, operations like filter(), map() will have no effect if Either was Left.
It helps to reduce the amount of code and to increase the robustness. A first step towards functional programming is to start thinking in immutable values. Vavr provides immutable collections and the necessary functions and control structures to operate on these values. The results are beautiful and just work.
Vavr is a functional library for Java 8+ that provides immutable data types and functional control structures.
There's a for comprehension construct in vavr that you could use for your use case. It helps you transform multiple Iterable
, Option
, Try
, Future
or List
instances to another Iterator
, Option
, Try
, Future
or List
instance respectively, by combining them (as rows of their cartesian product) into result values.
In your case, Either
being an Iterable
on the right value, you can use the For
construct for Iterable
s to construct a Tuple3
of the String
right values, and iterate over the resulting Iterator
by invoking your side-effecting code, or mapping/transforming them in whatever way you want. You will have a rich vavr Iterator
, so that's a lot more flexible than a simple JDK Iterator
.
import static io.vavr.API.For;
For(either1, either2, either3)
.yield(Tuple::of)
.forEach(t -> methodRequiringAllInputs(t._1, t._2, t._3));
One small note though: in the above case, the result from the yield
is a lazily evaluated Iterator
. That means you'll need to iterate over it in the end in order to have the effects executed, so the forEach
part is essential. You cannot move the side-effecting code into the yield
part and skip the forEach
, as the yield
part will only be (lazily) executed when the resulting Iterator
is being iterated over.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With