Skip to content

jbock-java/either

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

either

either:1.5

The Either type is closely related to Optional, but can have different "failure" states, other than only empty. Either can be used to collect error messages in stream operations, or simply as a lightweight alternative to throwing an Exception.

There are several popular libraries that offer an Either type, including vavr, fugue, and lambda. This particular Either is lightweight, and very easy to work with if you're already familiar with Optional.

empty to Left

Sometimes, it can be desirable to put something into the "empty" value of an Optional. Let's call this "adding a Left value", since this value is no longer empty. Adding a Left value is as easy as mapping with Either::right, followed by an orElseGet to supply the Left value:

Either<String, BigInteger> possiblyPrime = Stream.generate(() -> 
                ThreadLocalRandom.current().nextInt(1000))
        .map(BigInteger::valueOf)
        .limit(10)
        .filter(n -> n.isProbablePrime(10))
        .findAny()
        .<Either<String, BigInteger>>map(Either::right)
        .orElseGet(() -> Either.left("no such value"));

Declaring the result type before the map operation is necessary, due to limitations of Java's typechecker.

Working with Either

An Either has the familiar methods map, flatMap and filter. All of these work on Right Eithers, and leave a Left unchanged. This is intuitive, because the corresponding methods in Optional leave empty unchanged. Symmetrically there are mapLeft, flatMapLeft and filterLeft, which leave a Right unchanged instead.

Finally there is ifPresentOrElse ifLeftOrElse (1.3) and the all-powerful fold method, as well as getRight and getLeft to convert back to Optional.

Working with streams

If you have a stream of Either, you can search for failures using one of the collectors toValidList and toValidListAll:

Either<BigInteger, List<BigInteger>> twoPrimesOrOneComposite = Stream.generate(() ->
        ThreadLocalRandom.current().nextInt(1000))
        .map(BigInteger::valueOf)
        .limit(2)
        .<Either<BigInteger, BigInteger>>map(n -> n.isProbablePrime(10) ?
                Either.right(n) : Either.left(n))
        .collect(Eithers.toValidList());

Testimonies

This library grew for several months as part of the jbock project, until it was released independently. jbock uses it internally to perform input validation, and its generated parse method returns an Either.

Either gang