This is becoming a well covered subject. But I feel this is so awesome I want to share my insight.

Context

I'm developing an OAuth login process for my play2 app: www.trendytics.com

OAuth requires some round trips to exchange information.

Furthermore I am incrementally fetching information.

So play 2 has this awesome interface to fetch urls with post/get variables:

WS.url("www.google.com")

You can then further compose this with headers and parameters, make a GET or POST request, transform it to json, etc.

At one point I needed to make 3 of these url calls each of which requiring information from the previous call.

I kept getting errors in them.. so I toke a different approach

Enter Either

Either encodes two return types. Traditionally people put Errors and Successs in them but you can put whatever you like/need.

So, with Either you can encode successes and errors.

What makes it interesting? Well, you can make this:

type Error = String type Success = String def call(url:String):Either[Error,Success]={ val response = WS.url(url).get.value.get if (valid(response)) Right(response.body) else Left("Response is not valid") }

This returns a Success or an Error (both Strings in this case) if a valid function does not accept the response.

Left() creates an Either instance with the left element assigned (in this case an error).

Right() does the opposite.

In practice those instantiate Left and Right classes which are sub classes of the Either type, but are treated as Either

Furthemore you can even add exception handling to that..

So what, you ask?

Well, now we work with the Either

Each caller now has the ability to further refine the Success value or return an Error if it fails - which will fail the whole operation with an error message

Example:

def example(parameter:String):Either[Error,Success]= for (parameter1 <- call("www.site.com/parameter").right; parameter2 <- call("www.site.com/"+parameter1).right; parameter3 <- call("www.site.com/"+parameter2).right) yield (parameter3)

And this calls each url and combines the three calls where each is only done if the previous succeeded.

In summary: combining three errorsome calls, without losing data nor exploding in the user's face, into one beautiful package.

Finally, we can return the success or show the errors messages if there are any. But the processing in between didn't need to know about that.

What I'm doing is folding it:

example("parameter").fold(treatIfErrors(), treatIfSuccess())

These functions return the same type. Fold can then be used to unify your processing results, treating errors and successes as required.

How do you do it in your favorite programming language? (without if and elses)