Some time ago, I was watching this excellent video course by Neal Ford titled “Functional Thinking – Functional Programming using Java, Clojure and Scala”. In one of the modules on functional data structures, Neal talks about this container type in Scala named Either.
The Either type in Scala represents one of two possible values, a Left value or a Right value. The convention dictates that the Left value is used for error or exception objects, while the Right value is used for normal values. Why is this useful?
In many programming languages, like Java, C#, JavaScript, Scale, etc. …, there are generally two ways a function or method call returns something. The first one is through a regular return value that is returned by a function/method, be it some primitive type or some object. The second one is by throwing an exception, which means that the return value of the function/method in question is not available to the calling code. In order to deal with this dual behavior, the calling code has to verify/use the value returned when invoking a function or method as well as dealing with possible exceptions that this function/method might throw.
This is where the Either type comes in, unifying both behaviors by offering a Left value containing a possible error/exception object or a Right value containing the regular output of a function/method. In his course, Neal further elaborates on this concept by implementing a similar Either type in Java using interfaces because Java has no support for lambda’s yet (ouch).
While working on some JavaScript code a while back, I ran into this situation where the code in question could really benefit by using the concept of an Either object. So I decided to implement such an object in JavaScript and extracted the result into a Node.js module named either.js that I recently published on npm.
Take a look at the following code sample:
There were a couple of functions like this one where an array was being retrieved from an object named _dataAreas which contains a number of array properties. In case the specified property name could not be found on the containing object, the callback was invoked with an error object. Using an Either object, this code got revamped into something like this:
_this.insertReport = function(dataArea, inventoryReport, callback) {
simulateAsynchronousIO(function() {
var reportsCollection = _dataAreas[dataArea];
if(!reportsCollection) {
var error = new InvalidDataAreaError('The specified area is unknown.');
callback(error);
return;
}
reportsCollection.push(inventoryReport);
callback();
});
};
I admit that there’s definitely some getting used to at first, but I find this approach to be very clean and useful. In fact, this kind of reminds me to the beauty of using promises for asynchronous code, but for synchronous code instead.
Until next time.