# 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(); } } ```
Option all the things
## 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
## We can do better...
## Map aka Transform ```java class RightProjection<L, R> { <X> Either<L, X> map(Function<R, X> f) } ```

Warning

Danger Will Robinson

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)
## Conclusion
## 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)