Overview of vavr Option API.
Reference: http://www.vavr.io/vavr-docs/#_option
Reference: https://static.javadoc.io/io.vavr/vavr/0.9.2/io/vavr/control/Option.html
Reference: https://softwaremill.com/do-we-have-better-option-here/
Reference: http://blog.vavr.io/the-agonizing-death-of-an-astronaut/
Option is a monadic container type which represents
an optional value. Instances of Option are either an
instance of Option.Some or the singleton Option.None.
If you’re coming to Vavr after using Java’s Optional class,
there is a crucial difference. In Optional, a call to
.map that results in a null will result in an empty
Optional. In Vavr, it would result in a Some(null) that
can then lead to a NullPointerException.
This seems like Vavr’s implementation is broken, but in
fact it’s not - rather, it adheres to the requirement
of a monad to maintain computational context when
calling .map. In terms of an Option, this means that
calling .map on a Some will result in a Some, and
calling .map on a None will result in a None. In the
Java Optional example above, that context changed from
a Some to a None.
There are two functions that operate on Monads,
map and flatMap. These obey specific laws.
For this project it is sufficient to say that map has to
preserve the computational context of a value. For
context changes flatMap is used.
The constructor Option.of(value) puts a value into a
computational context. If the value is null, the context
is None, otherwise the context is Some.
Preserving this context means:
Some(value).map(v -> otherValue) ~ Some(otherValue)None().map(v -> otherValue) ~ None()
We do not expect context changes when mapping values. It would break the Monad laws.
We provide description and tests of Option methods.
Option<T> narrow(Option<? extends T> option)- Narrows a widenedOption<? extends T>toOption<T>by performing a type-safe cast.note thatOption<String> a = Option.of("a"); Option<CharSequence> narrowed = Option.narrow(a);Option<String> a = null; assertNull(Option.narrow(a));Option<T> none()- Returns the single instance ofNoneassertSame(Option.none(), Option.none());Option<T> of(T value)- Creates a newOptionof a given value.Some(value)if value is not null,NoneotherwiseOption<Object> option = Option.of("a"); assertThat(option.get(), is("a"));Option<Object> option = Option.of(null); assertTrue(option.isEmpty());Option<T> ofOptional(Optional<? extends T> optional)- Wraps aJava Optionalto a newOption.Some(optional.get())if value is JavaOptionalis present,Noneotherwise.Option.ofOptional(null); // throws NPEOption<Seq<T>> sequence(Iterable<? extends Option<? extends T>> values)- Reduces manyOptionsinto a singleOptionby transforming anIterable<Option<? extends T>>into aOption<Seq<T>>.If any of theOption<Seq<String>> sequence = Option.sequence(List.of(Option.of("a"), Option.of("b"))); assertTrue(sequence.get().eq(List.of("a", "b")));OptionsareOption.None, then this returnsOption.None.Option<Seq<String>> sequence = Option.sequence(List.of(Option.of("a"), Option.of("b"), Option.none())); assertTrue(sequence.isEmpty());Option<T> some(T value)- Creates a newSomeof a given value.difference toOption<Object> some = Option.some(null); assertTrue(some.isDefined()); assertTrue(some instanceof Option.Some); assertNull(some.get());of():Option.of(null); // = None Option.some(null); // = Some(null)Option<T> when(boolean condition, Supplier<? extends T> supplier)- CreatesSomeof suppliers value if condition is true, orNonein other caseOption<T> when(boolean condition, T value)- CreatesSomeof value if condition is true, orNonein other caseOption<Integer> when = Option.when(false, 1); assertTrue(when.isEmpty());Option<Integer> when = Option.when(true, 1); assertTrue(when.isDefined());Option<Integer> when = Option.when(true, (Integer) null); assertTrue(when.isDefined());
-
Option<R> collect(PartialFunction<? super T,? extends R> partialFunction)- Collects value that is in the domain of the givenpartialFunctionby mapping the value to typeR.assertThat(Option.of("a").collect(PartialFunctionExample.stringLength), is(Option.some(1)));assertThat(Option.of("b").collect(PartialFunctionExample.stringLength), is(Option.none()));where inPartialFunction:
static PartialFunction<String, Integer> stringLength = new PartialFunction<>() { @Override public Integer apply(String s) { return isNull(s) ? 0 : s.length(); } @Override public boolean isDefinedAt(String value) { return Objects.equals("a", value); } }; -
boolean equals(Object o)- ifSomecallequalson values@Override public boolean equals(Object obj) { return (obj == this) || (obj instanceof Some && Objects.equals(value, ((Some<?>) obj).value)); } -
Option<T> filter(Predicate<? super T> predicate)default Option<T> filter(Predicate<? super T> predicate) { Objects.requireNonNull(predicate, "predicate is null"); return isEmpty() || predicate.test(get()) ? this : none(); }assertThat(Option.none().filter(x -> true), is(Option.none()));assertThat(Option.some(1).filter(x -> false), is(Option.none()));assertThat(Option.some(1).filter(x -> true), is(Option.of(1)));
-
Option<U> flatMap(Function<? super T,? extends Option<? extends U>> mapper)default <U> Option<U> flatMap(Function<? super T, ? extends Option<? extends U>> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isEmpty() ? none() : (Option<U>) mapper.apply(get()); }assertThat(Option.of(Option.of(1)).flatMap(Function.identity()), is(Option.of(1)));assertThat(Option.of(Option.some(null)).flatMap(Function.identity()), is(Option.some(null)));assertThat(Option.none().flatMap(x -> null), is(Option.none()));assertNull(Option.of(1).flatMap(x -> null));- difference to java
OptionalflatMap:Optional.of(1).flatMap(x -> null);throws NPE
-
T get()-NoSuchElementExceptionifthisis aNone.assertNull(Option.some(null).get());
-
T getOrElse(Supplier<? extends T> supplier) -
T getOrElse(T other) -
<X extends Throwable> T getOrElseThrow(Supplier<X> exceptionSupplier) -
boolean isDefined()assertTrue(Option.some(null).isDefined());
-
boolean isEmpty() -
Option<U> map(Function<? super T,? extends U> mapper)Option<U> map(Function<? super T, ? extends U> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return isEmpty() ? none() : some(mapper.apply(get())); }assertThat(Option.some(null).map(Function.identity()), is(Option.some(null)));assertThat(Option.of(1).map(x -> null), is(Option.some(null)));assertThat(Option.of(1).map(Function.identity()), is(Option.some(1)));assertThat(Option.<Integer>none().map(Function.identity()), is(Option.none()));- difference to java
Optionalmap:assertThat(Optional.of(1).map(x -> null), is(Optional.empty()));
-
Option<T> onEmpty(Runnable action)- Runs a JavaRunnablepassed as parameter if thisOptionis empty. -
Option<T> orElse(Option<? extends T> other) -
Option<T> orElse(Supplier<? extends Option<? extends T>> supplier)assertThat(Repository.findById(1).orElse(Repository.findByName("Michal")), is(Option.of("found-by-id")));assertThat(Repository.findById(1).orElse(Repository.findByName("Michal")), is(Option.of("found-by-name")));whereRepository:
static Option<String> findById(int id) { return Option.when(id == 1, "found-by-id"); } static Option<String> findByName(String name) { return Option.when(Objects.equals(name, "Michal"), "found-by-name"); } -
Option<T> peek(Consumer<? super T> action)- applies an action to this value, if this option is defined, otherwise does nothing. It is useful to constructif-else(ifPresentOrElseinOptional API) statements:AtomicBoolean invokedPeek = new AtomicBoolean(); AtomicBoolean invokedOnEmpty = new AtomicBoolean(); Option.of(1).peek(x -> invokedPeek.set(true)) .onEmpty(() -> invokedOnEmpty.set(true)); assertTrue(invokedPeek.get()); assertFalse(invokedOnEmpty.get());AtomicBoolean invokedPeek = new AtomicBoolean(); AtomicBoolean invokedOnEmpty = new AtomicBoolean(); Option.none().peek(x -> invokedPeek.set(true)) .onEmpty(() -> invokedOnEmpty.set(true)); assertFalse(invokedPeek.get()); assertTrue(invokedOnEmpty.get());AtomicBoolean invokedPeek = new AtomicBoolean(); Integer value = Option.of(1).peek(x -> invokedPeek.set(true)) .getOrElse(-1); assertTrue(invokedPeek.get()); assertThat(value, is(1));AtomicBoolean invokedPeek = new AtomicBoolean(); Integer value = Option.<Integer>none().peek(x -> invokedPeek.set(true)) .getOrElse(-1); assertFalse(invokedPeek.get()); assertThat(value, is(-1)); -
U transform(Function<? super Option<T>,? extends U> f)U transform(Function<? super Option<T>, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); }it is useful to transform
Optionalinto collection:var collection = Option.of(1) .transform(option -> option.map(List::of).getOrElse(Collections::emptyList)); assertThat(collection, is(List.of(1)));var collection = Option.<Integer>none() .transform(option -> option.map(List::of).getOrElse(Collections::emptyList)); assertThat(collection, is(empty()));note that you could simply use:
Option.of(1).map(List::of).getOrElse(Collections::emptyList);