# Fun with Fugue and Functions
## Me
* Charles O'Farrell
* Atlassian
* [@charlesofarrell](http://twitter.com/charlesofarrell)
## What is [Fugue](https://bitbucket.org/atlassian/fugue)
* Atlassian open source library
* Extensions to [Guava](http://code.google.com/p/guava-libraries/)
> In music, a fugue is a [compositional](http://en.wikipedia.org/wiki/Fugue) technique with two or more voices,
> built on a subject that is introduced at the beginning in imitation
> and recurs frequently in the course of the composition.
## Isn't Guava open source?
I'll let [them](https://plus.google.com/113026104107031516488/posts/ZRdtjTL1MpM) speak for themselves
> Many of you, when you request a feature for Guava, have submitted a patch to us with the implementation.
> And we have almost never accepted any of these patches, let alone even read them.
## Guava - what they missed
* Option (Optional is [broken](http://benhutchison.wordpress.com/2012/06/05/a-rant-on-jdroids-and-wilful-ignorance/))
* Either
* Pair (aka Tuple)
* Utils
* Functions
* Iterables
* Suppliers
## What's wrong with this code?
```java
public Foo someMethod()
someMethod().doSomething()
```
## Look again
```java
@Nullable
public Foo someMethod()
someMethod().doSomething()
```
## By the power of Greyskull
```java
public Nullable<Foo> someMethod()
// Won't compile
someMethod().doSomething()
```
## Introducing Option (conceptual)
```java
interface Option<A>
class Some<A> implements Option<A> {
private final A value;
public Some(A value) {
this.value = value;
}
}
class None implements Option<Object>
```
- Collection with none or one element
## Revenge of the null
```java
Map<String, Conflict> conflicts = ...
InternalChange change = parseChange(line);
Conflict conflict = conflicts.get(change.getPath());
if (conflict == null) {
conflict = conflicts.get(change.getSrcPath());
}
if (conflict != null) {
change = builder.conflict(conflict).build();
}
```
## java.util.Map
```java
class Map<K, V> {
@Nullable
V get(K key)
}
```
## What if...
```java
class Map<K, V> {
Option<V> get(K key)
}
```
## More Options
```java
abstract class Option<A> {
boolean isEmpty()
boolean isDefined()
A get() throws NoSuchElementException
}
```
## Option as null
```java
Map<String, Conflict> conflicts = ...
InternalChange change = parseChange(line);
Option<Conflict> conflict = conflicts.get(change.getPath());
if (conflict.isEmpty()) {
conflict = conflicts.get(change.getSrcPath());
}
if (conflict.isDefined()) {
change = builder.conflict(conflict.get()).build();
}
```
## Option as null
* Already better than null
* Type-safety vs documentation
* Developers have to stop and think
* But, get is ugly...
## Use Option or else
```java
abstract class Option<A> implements Iterable<A> {
Option<A> orElse(Option<A> orElse)
}
```
## Composing Option
```java
Option<Conflict> conflictOption =
conflicts.get(change.getPath()).orElse(conflicts.get(change.getSrcPath()));
for (Conflict conflict : conflictOption) {
change = builder.conflict(conflict).build();
}
```
## Seems familiar
```js
var value = map['a'] || map['b'] || 'c'
```
```java
Option[String] value = map.get("a").orElse(map.get("b")).orElse(new Some("c"))
```
## Get or else
```java
abstract class Option<A> {
<B extends A> A getOrElse(B other)
}
```
## Seems familiar (part 2)
```js
var value = map['a'] || map['b'] || 'c'
```
```java
String value = map.get("a").orElse(map.get("b")).getOrElse("c")
```
## Seen this before?
```java
InetSocketAddress socketAddress = session.getIoSession().getRemoteAddress();
if (socketAddress != null) {
InetAddress inetAddress = socketAddress.getAddress();
if (inetAddress != null) {
remoteAddress = inetAddress.getHostAddress();
}
}
```
## Another useful Option
```java
abstract class Option<A> {
static <A> Option<A> some(A a)
static <A> Option<A> none()
static <A> Option<A> option(A a)
}
```
## Not a null in sight
```java
for (InetSocketAddress socketAddress : option(session.getIoSession().getRemoteAddress())) {
for (InetAddress inetAddress : option(socketAddress.getAddress())) {
remoteAddress = inetAddress.getHostAddress();
}
}
```
## Is Option a better null?
- Type safety
- Just a collection
- Can filter/transform/concat/etc
- Composition!
## Another example
```java
public ModelAndView browseFilePath() {
Repository repository = getRepository(projectKey, repoSlug);
if (repository == null) {
return handleEmptyRepo();
}
Branch defaultBranch = getDefaultBranch(repository);
if (defaultBranch == null) {
return handleNoDefaultBranch(repository);
}
return doSomething(defaultBranch);
}
```
## What do we want?
```java
public ModelAndView browseFilePath() {
return doSomething(getRepositoryAndBranch());
}
public ModelAndView diffFilePath() {
return doSomethingElse(getRepositoryAndBranch());
}
```
## Could we use Option?
```java
Option<Repository> getRepository()
Option<Branch> getDefaultBranch()
```
## Could we use Option?
```java
public ModelAndView browseFilePath() {
for (Repository repository : getRepository(projectKey, repoSlug)) {
for (Branch defaultBranch : getDefaultBranch(repository)) {
return doSomething(defaultBranch);
}
return handleNoDefaultBranch(repository);
}
return handleEmptyRepo();
}
```
```java
public ModelAndView diffFilePath() {
// Same as above...
}
```
## Could we use Option?
* In short - no!
* Too much code duplication
## Use Exceptions?
```java
public Repository getRepository() throws ModelAndViewException {
Repository repository = repositoryService.findBySlug(projectKey, repoSlug);
if (repository == null) {
throw new ModelAndViewException(handleEmptyRepo());
}
return repository;
}
```
```java
public Branch getRepositoryAndBranch() throws ModelAndViewException {
Repository repository = getRepository(projectKey, repoSlug);
return getDefaultBranch(repository);
}
```
## I take Exception to that
```java
public ModelAndView browseFilePath() {
try {
return doSomething(getRepositoryAndBranch());
} catch (ModelAndViewException e) {
return e.getModelAndView();
}
}
```
```java
public ModelAndView diffFilePath() {
try {
return doSomethingElse(getRepositoryAndBranch());
} catch (ModelAndViewException e) {
return e.getModelAndView();
}
}
```
## What is this really saying?
```java
Repository getRepository() throws ModelAndViewException
```
Can this be expressed as a function - only one return type?
Return _either_ ModelAndView or Repository
```java
Either<ModelAndView, Repository> getRepository()
```
## Either (conceptual)
```java
interface Either<L, R>
class Left<L> implements Either<L, R> {
private final L value;
public Left(L value) {
this.value = value;
}
}
class Right<R> implements Either<L, R> {
private final R value;
public Right(R value) {
this.value = value;
}
}
```
## Either
```java
abstract class Either<L, R> {
static <L, R> Either<L, R> left(L left);
static <L, R> Either<L, R> right(R right);
}
```
## Either as exceptions
```java
public Either<ModelAndView, Repository> getRepository() {
Repository repository = repositoryService.findBySlug(projectKey, repoSlug);
if (repository == null) {
return left(handleEmptyRepo());
}
return right(repository);
}
```
## Either Projection
```java
abstract class Either<L, R> {
Projection<L> left()
Projection<R> right()
}
class Projection<A> implements Iterable<A> {
A get() throws NoSuchElementException
}
```
## Either to the rescue
```java
public Either<ModelAndView, Branch> getRepositoryAndBranch() {
Either<ModelAndView, Repository> repositoryE = getRepository(projectKey, repoSlug);
for (Repository repository : repositoryE.right()) {
return getDefaultBranch(repository);
}
// Yuck! We'll come back to this...
return left(repositoryE.left().get());
}
```
## Are we there yet?
```java
public ModelAndView browseFilePath() {
Either<ModelAndView, Branch> branchE = getRepositoryAndBranch();
for (Branch branch : branchE.right()) {
return doSomething(branch);
}
return branchE.left().get();
}
public ModelAndView diffFilePath() {
Either<ModelAndView, Branch> branchE = getRepositoryAndBranch();
for (Branch branch : branchE.right()) {
return doSomethingElse(branch);
}
return branchE.left().get();
}
```
![Not bad](http://29.media.tumblr.com/tumblr_lltzgnHi5F1qzib3wo1_400.jpg)
## Either
- Like checked exceptions
- Just a return value
- No special syntax
- But
- Still some code re-use
- Calling get is ugly
## Map aka Transform
```java
class RightProjection<L, R> {
<X> Either<L, X> map(Function<R, X> f)
}
```
Warning
Things are going to get functional...
Switch to IntelliJ mode
## The functional way
```java
public Either<ModelAndView, ModelAndView> browseFilePath() {
return getRepositoryAndBranch().right().map(Function(Branch defaultBranch) {
return doSomething(defaultBranch);
});
}
```
## Merge it
```java
abstract class Either<L, R> {
static <T> T merge(Either<T, T> either)
}
```
## Ship it
```java
public ModelAndView browseFilePath() {
return merge(getRepositoryAndBranch().right().map(Function(Branch defaultBranch) {
return doSomething(defaultBranch);
}));
}
```
## From before
### Could we use map?
```java
public Either<ModelAndView, Branch> getRepositoryAndBranch() {
Either<ModelAndView, Repository> repositoryE = getRepository(projectKey, repoSlug);
for (Repository repository : repositoryE.right()) {
return getDefaultBranch(repository);
}
return left(repositoryE.left().get());
}
```
## Turtles all the way down
```java
public Either<ModelAndView, Either<ModelAndView, Branch>> getRepositoryAndBranch() {
return getRepository(projectKey, repoSlug).right().map(Function(Repository repository) {
return getDefaultBranch(repository);
});
}
```
## Down the rabbit hole
```java
class RightProjection<L, R> {
<X> Either<L, X> flatMap(Function<R, Either<L, X>> f)
}
```
## FlatMap that shit
```java
public Either<ModelAndView, Branch> getRepositoryAndBranch() {
return getRepository(projectKey, repoSlug).right()
.flatMap(Function(Repository repository) {
return getDefaultBranch(repository);
});
}
```
## But wait, there's more...
## From before
```java
for (InetSocketAddress socketAddress : option(session.getIoSession().getRemoteAddress())) {
for (InetAddress inetAddress : option(socketAddress.getAddress())) {
remoteAddress = inetAddress.getHostAddress();
}
}
```
## Even more Options
```java
class Option<A> {
<B> Option<B> map(Function<? super A, B> f)
<B> Option<B> flatMap(Function<? super A, Option<B>> f)
}
```
## With flatMap/map
```java
remoteAddress = session.getIoSession().getRemoteAddress()
.flatMap(Function(InetSocketAddress socketAddress) {
return socketAddress.getAddress();
})
.map(Function(InetAddress inetAddress) {
return inetAddress.getHostAddress();
});
```
## Spot the pattern?
```java
session.getIoSession().getRemoteAddress()
.flatMap(Function(InetSocketAddress socketAddress) {
return socketAddress.getAddress();
})
.map(Function(InetAddress inetAddress) {
return inetAddress.getHostAddress();
})
```
```java
getRepository(projectKey, repoSlug).right()
.flatMap(Function(Repository repository) {
return getDefaultBranch(repository);
}).right()
.map(Function(Branch defaultBranch) {
return doSomething(defaultBranch);
})
```
## Abstract all the things
```java
class Option<A> {
<B> Option<B> map(Function<A, B> f)
<B> Option<B> flatMap(Function<A, Option<B>> f)
}
```
```java
class RightProjection<L, R> {
<X> Either<L, X> map(Function<R, X> f)
<X> Either<L, X> flatMap(Function<R, Either<L, X>> f)
}
```
## What shall we call it?
```java
interface WarmFuzzyThing<A> {
<B> WarmFuzzyThing<B> map(Function<A, B> f)
<B> WarmFuzzyThing<B> flatMap(Function<A, WarmFuzzyThing<B>> f)
}
```
#Monad!
```java
interface Monad<A> {
<B> Monad<B> map(Function<A, B> f)
<B> Monad<B> flatMap(Function<A, Monad<B>> f)
}
```
Note: Not expressible in Java.
## Scala Syntactic sugar
```scala
for {
socketAddress <- session.getIoSession().getRemoteAddress()
inetAddress <- socketAddress.getAddress()
} yield inetAddress
```
```scala
for {
repository <- getRepository(projectKey, repoSlug).right
defaultBranch <- getDefaultBranch(repository).right
} yield defaultBranch
```
## Further reading
* [http://www.infoq.com/presentations/Value-Values]()
* Or anything by [Rich Hickey](https://twitter.com/richhickey)
## More tools
![Tools](http://socialmediatoday.com.au/wp-content/uploads/2012/08/Tools.jpg)
* Options are a better null
* Eithers are a better checked exception
## Composition, composition, composition
![Lego](http://lukemsblog.global2.vic.edu.au/files/2012/02/Lego-2-2hl0790.jpg)
## Monads are out there
![](http://images-cdn01.associatedcontent.com/image/A2034/203477/300_203477.jpg)