'How to get Either left/right depending of Option value
I'm trying to return Either value depending on option value. My goal is to return Either.right() if the option is present otherwise, the code should return Either.left().
I use Java 8 and vavr 0.9.2
I want to avoid conditional imbrication
public Either<String, Integer> doSomething() {
Optional<Integer> optionalInteger = Optional.of(Integer.MIN_VALUE);
Option<Integer> integerOption = Option.ofOptional(optionalInteger);
return integerOption.map(value -> {
//some other actions here
return Either.right(value);
}).orElse(() -> {
//some other checks her also
return Either.left("Error message");
});
}
the compiler fail with this message
Error:(58, 7) java: no suitable method found for orElse(()->Either[...]age"))
method io.vavr.control.Option.orElse(io.vavr.control.Option<? extends io.vavr.control.Either<java.lang.Object,java.lang.Integer>>) is not applicable
(argument mismatch; io.vavr.control.Option is not a functional interface
multiple non-overriding abstract methods found in interface io.vavr.control.Option)
method io.vavr.control.Option.orElse(java.util.function.Supplier<? extends io.vavr.control.Option<? extends io.vavr.control.Either<java.lang.Object,java.lang.Integer>>>) is not applicable
(argument mismatch; bad return type in lambda expression
no instance(s) of type variable(s) L,R exist so that io.vavr.control.Either<L,R> conforms to io.vavr.control.Option<? extends io.vavr.control.Either<java.lang.Object,java.lang.Integer>>)
Solution 1:[1]
orElse returns Option<T> while doSomething return type requires Either<String, Integer>.
Instead, try to use getOrElse which returns T:
public Either<String, Integer> doSomething() {
// ...
return integerOption.map(
Either::<String, Integer>right).getOrElse(
() -> Either.left("Error message"));
}
Solution 2:[2]
Since you want to return Either<...> not an Option<Either<...>> you have to use getOrElse
Solution 3:[3]
I think redundant generics and formatting in @oleksandr-pyrohov's answer overcomplicate things a bit. I'd just write it this way instead:
public Either<String, Integer> doSomething() {
// ...
return integerOption
.map(Either::right)
.orElseGet(() -> Either.left("Error message"));
}
Upd.: though it does not seem to always infer generics on it's own sadly.
Solution 4:[4]
It works for me
public Either<String, Integer> doSomething() {
// ...
return integerOption
.<Either<String, Integer>>map(Either::right)
.orElseGet(() -> Either.left("Error message"));
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | adil.hilmi |
| Solution 3 | |
| Solution 4 | luprogrammer |
