https://github.com/jbock-java/either
Functional error handling for Java
https://github.com/jbock-java/either
either either-monad error-handling idiomatic java-either java-streams java11
Last synced: 5 months ago
JSON representation
Functional error handling for Java
- Host: GitHub
- URL: https://github.com/jbock-java/either
- Owner: jbock-java
- License: mit
- Created: 2021-07-02T15:47:27.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-10-24T05:32:03.000Z (7 months ago)
- Last Synced: 2024-12-07T14:51:31.306Z (5 months ago)
- Topics: either, either-monad, error-handling, idiomatic, java-either, java-streams, java11
- Language: Java
- Homepage:
- Size: 271 KB
- Stars: 41
- Watchers: 1
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://maven-badges.herokuapp.com/maven-central/io.github.jbock-java/either)
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](https://github.com/vavr-io/vavr), [fugue](https://bitbucket.org/atlassian/fugue/src/master/), and [lambda](https://github.com/palatable/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*.
Going from Optional to Either is as easy as mapping with `Either::right`,
followed by an `orElseGet` to supply the Left value:````java
Either possiblyPrime = Stream.generate(() ->
ThreadLocalRandom.current().nextInt(1000))
.map(BigInteger::valueOf)
.limit(10)
.filter(n -> n.isProbablePrime(10))
.findAny() // Optional
.>map(Either::right) // Optional>
.orElseGet(() -> Either.left("no such value")); // Either
````Repeating the result type in the penultimate line is necessary, due to a limitation of Java's typechecker.
### Working with Either
`Either` has the familiar methods from `Optional`: `map`, `flatMap` and `filter`.
These will always return a *Left* value unchanged,
just like the corresponding methods in `Optional`, which return an *empty* value unchanged.Symmetrically there are `mapLeft`, `flatMapLeft` and `filterLeft`, which return a *Right* value unchanged.
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 *Left* values with custom collectors
`firstFailure` or `allFailures`:````java
Either> twoPrimesOrOneComposite = Stream.generate(() ->
ThreadLocalRandom.current().nextInt(1000))
.map(BigInteger::valueOf)
.limit(2)
.>map(n -> n.isProbablePrime(10) ?
Either.right(n) : Either.left(n))
.collect(Eithers.firstFailure());
````### Testimonies
This library grew for several months as part of the [jbock](https://github.com/jbock-java/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
* [spencerwi](https://github.com/spencerwi/Either.java)
* [ambivalence](https://github.com/poetix/ambivalence)
* [derive4j](https://github.com/derive4j/derive4j)
* [mediascience](https://github.com/mediascience/java-either)
* [pragmatica](https://github.com/siy/pragmatica)
* [gradle's internal either](https://github.com/gradle/gradle/tree/master/subprojects/functional)
* [dichotomy](https://github.com/xyzsd/dichotomy)