Forget Optional<T>, adopt Try<T>?

Jed Wesley-Smith jed at
Tue Jun 4 00:52:26 PDT 2013

Actually Try is a (sort of*) monad on exception handling. It is really an
Either (or disjunction) class that is specialised to catch exceptions
during map/flatMap.

As you point out, Option is isomorphic to an Either with no useful value on
the left hand side (Unit or Void for instance), and a true Either can
return something meaningful as to the reason why there was nothing.

Making something that was returning @Nullable T an Optional<T> simply says
to the client, "there may not be a return value here". Making it return an
Either<X, T> says to the client "there may not be a return value here and X
is why". This is actually not necessary in many cases. Imagine a
Map.getOptional, there is no real reason to supply
BecauseThisMapDidntContainValue on the left hand side if the key isn't
found– it is somewhat obvious.

So, while Either and Option to serve similar purposes, there are important
differences. Rather than choose one, you really want to have both in the


* it is sort of a monad as a monad should really obey the contravariant
functor laws, and it doesn't due to the fact that composition is violated:

On 4 June 2013 14:21, Zhong Yu <zhong.j.yu at> wrote:

> I'm thinking that if we have something like scala's Try<T>, it'll
> express APIs' intentions better than Optional<T>.
> Some people view Optional as a collection of either 0 or 1 element.
> That doesn't seem to be what an API author wants to express by
> returning an Optional. The actual intention is that, either the action
> succeeds with a value (not a collection of!), or it fails (with an
> unspecified or implied reason). Try<T> describes that intention
> precisely (but it probably needs a better name)
> Suppose we have a good old method that returns a nullable
>     /** return null if there's no element */
>     T getFirst();
> Why do we hate it? Probably because we need to insert null handling in
> the code path
>     T first = getFirst();
>     if(first==null)
>         blah blah
>     first.doSomething()...
> we would rather defer null handling to some later time, leaving the
> main code path cleaner. Java already has a way to do that - exception
> propagation. For example the method can be designed to throw
>     T getFirst() throw NotFoundExcpetion;
>     // for efficiency, throw a cached immutable exception object
>     T first = getFirst();  // may throw - exception will be handled
> somewhere else
>     // no null handling here
>     first.doSomething()
> But lots of try-catch blocks may make code look ugly. Try<T> may be nicer
>     /** fail with NotFoundException if  there's no element */
>     Try<T> getFirst();
>     Try<T> first = getFirst();
> So we don't need Optional. Try<T> does the same thing, and expresses
> the intention better. And Try<T> has broader use cases. It'll also
> appease those who prefer returning errors over throwing errors.
> Sounds good?
> Zhong Yu

More information about the lambda-dev mailing list