https://github.com/mtumilowicz/java11-vavr093-option-workshop
Vavr Option workshop.
https://github.com/mtumilowicz/java11-vavr093-option-workshop
option vavr vavr-option workshop workshop-materials workshops
Last synced: 3 days ago
JSON representation
Vavr Option workshop.
- Host: GitHub
- URL: https://github.com/mtumilowicz/java11-vavr093-option-workshop
- Owner: mtumilowicz
- License: gpl-3.0
- Created: 2019-03-02T22:23:50.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2019-07-28T08:31:05.000Z (almost 7 years ago)
- Last Synced: 2025-06-01T12:54:49.367Z (about 1 year ago)
- Topics: option, vavr, vavr-option, workshop, workshop-materials, workshops
- Language: Groovy
- Homepage:
- Size: 133 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://travis-ci.com/mtumilowicz/java11-vavr093-option-workshop)
[](https://www.gnu.org/licenses/gpl-3.0)
# java11-vavr093-option-workshop
# project description
* https://www.vavr.io/vavr-docs/#_option
* https://static.javadoc.io/io.vavr/vavr/0.9.3/io/vavr/control/Option.html
* https://github.com/mtumilowicz/java11-vavr-option
* https://github.com/mtumilowicz/java11-category-theory-optional-is-not-functor
* in the workshop we will try to fix failing tests `test/groovy/Workshop`
* answers: `test/groovy/Answers` (same tests as in `Workshop` but correctly solved)
# theory in a nutshell
* similar to `Optional`, but with bigger, more flexible API
* `interface Option extends Value, Serializable`
* `interface Value extends Iterable`
* `Option` is isomorphic to singleton list (either has element or not, so it could be treated as collection)
* two implementations:
* `final class Some`
* `final class None`
* `None` instance is a singleton
* returning `null` inside `map` does not cause `Option` switch to `None` (contrary to `Optional`)
```
expect:
Option.some(2).map(alwaysNull).defined
Optional.of(2).map(alwaysNull).empty
```
* it is possible to have `Some(null)`, so `NPE` is possible even on defined `Option`
* excellent for modelling exists / not exists (Spring Data - `findById`)
* not every "exceptional" behaviour could be modelled as exists / not exists
# conclusions in a nutshell
* **we omit methods that `Optional` has**
* easy conversion `Option` <-> `Optional`
* `Option.ofOptional`
* `option.toJavaOptional()`
* handy conversion `List> -> Option>`
* `Option.sequence(list)`
* if any of the `Options` are `None` - returns `None`
* conditional supplier
* `static Option when(boolean condition, Supplier extends T> supplier)`
* mapping with the partial function
* `Option collect(PartialFunction super T, ? extends R> partialFunction)`
* if function is not defined for the value - returns `None`
* side effects on `None`
* `Option onEmpty(Runnable action)`
* side effects on `Some`
* `Option peek(Consumer super T> action)`
* lazy alternative (in `Optional` since 11)
* `Option orElse(Supplier extends Option extends T>> supplier)`
* `transform` function could be nearly always replaced with more expressive and natural `map(...).orElse(...)`
```
given:
Function, String> transformer = { it.isEmpty() ? '' : it.get().toString() }
expect:
Option.of(5).transform(transformer) == '5'
```
same as
```
given:
Function, String> transformer = { it.isEmpty() ? '' : it.get().toString() }
expect:
transformerFive = Option.of(5)
.map { it.toString() }
.orElse('') == '5'
```
* conversion `Option` <-> `List`
* `option.toList()`
* `list.toOption()`
* could be treated as collection
* `boolean contains(T element)`
* `boolean exists(Predicate super T> predicate)`
* `boolean forAll(Predicate super T> predicate)`
* well written equals
* `Some`
```
return (obj == this) || (obj instanceof Some && Objects.equals(value, ((Some>) obj).value));
```
* `None`
```
return o == this
```
* map does not breaks monadic laws
```
given:
Function alwaysNull = { null }
Function safeToString = { nonNull(it) ? String.valueOf(it) : 'null' }
Function composition = alwaysNull.andThen(safeToString)
expect:
Optional.of(1).map(composition) != Optional.of(1).map(alwaysNull).map(safeToString)
Optional.of(1).stream().map(composition).findAny() == Optional.of(1).stream()
.map(alwaysNull)
.map(safeToString)
.findAny()
Option.of(1).map(composition) == Option.of(1).map(alwaysNull).map(safeToString)
```