Multiple return (was: JEP 186: Collection Literals)
jed at wesleysmith.io
Wed Jan 22 13:36:10 PST 2014
(reposting to the list as I replied to Zhong Yu only)
On 22 January 2014 15:13, Zhong Yu <zhong.j.yu at gmail.com> wrote:
> There is value in meticulously handling error condition after each
> single action. Sometimes I wish Java had a simpler syntax to do just
> that (try-catch is too clunky).
Either style solutions force you to deal with error conditions, whereas a
multiple return does not.
> Go's solution for this kind of error
> handling strategy is syntactically beautiful.
No, it is horrid. Every call must be followed by an error check, eg in
// error handler
// happy path
> If someone wants to
> emulate that strategy in Java, `Either` won't work as beautifully
> (correct me if I'm wrong - but limit the solution to simple C style
You can do exactly the same in Java right now with a Pair<Err, A>. The real
point is that Either can only be an error OR a result, not both.
A useful Either class will also allow you to map/flatMap across the happy
Either<Err, String> a = someMethodThatReturnsEither();
Either<Err, Integer> b = a.map(String s -> s.length());
Either<Err, Integer> c = b.flatMap(Int i ->
and if an error is returned anywhere in lines 1 or 3 above, the final
Either will be an Err, otherwise it will be a result. We have encapsulated
error handling, and we can prove that that code correctly deals with
> Either<String, ErrorCode> search();
> // call site
> Either<String, ErrorCode> result = search();
> if(result.isRight()) // if it's right, it's wrong!
> handle result.getRight();
> use result.getLeft();
> // what the hell is this code talking about?
There are several combinators for handling Eithers, the most common being
the catamorphism, or fold method. It allows you to provide two methods that
each take one side of the Either and return a value of the destination type:
<X> X fold(Function<Err, X> errorHandler, Function<A, X> happy)
this can be used, for instance with the c value above:
String desc = c.fold(
e -> "An error occurred: " + e
, i -> "Result! " + i
Or, if you want side effects there are variations on foreach you can use
e -> send.error("An error occurred: " + e)
, i -> send.response("Result! " + i)
You can also use things like
Either<A, B> onRight(Sink<B> effect)
Either<A, B> onLeft(Sink<A> effect)
There are many other useful combinators available on a decent Either
Anyway, as Brian pointed out, there is nothing apart from an allocation
that the Go approach provides that is not already available in Java, and
much that Go cannot due to the absence of parametric polymorphism.
More information about the lambda-dev