Lately I’ve been studying OCaml. It’s a very nice language. In grad school I worked with Standard ML a bit, but never got a good feel for it. OCaml feels very comfortable, although I am still learning to write idiomatically.
OCaml will let you be as pure as you need to be, but will also let you wallow in the gutter of mutable variables if you need to. It is less judgmental than some other languages.
One of these compromises is in how OCaml uses exceptions. That got me thinking about handling exceptions in ramda. For example, suppose you have a list of a billion integers, and you need to get a product over the whole list:
This is a bit naive. The biggest problem is what if I encounter a zero? At
that point I know that the whole product will be zero. I can stop multiplying.
if check doesn’t quite solve the problem:
What if zero is the last integer in the list? I have built up nearly a billion recursive calls in my stack that I still have to unwind. This is the kind of grimy, real-world consideration that some functional programmers like to sweep under the rug.
OCaml lets you solve this very nicely using exceptions. In the example above
I could define an exception
Zero and raise it if I encounter a zero in my list:
Now we have to handle the exception:
How nice is that? The exception will short-circuit the evaluation, throw away any stack I have built up, and return me an answer.
Unfortunately, there is nothing in the signature to indicate that this function might raise an exception:
I can get a “safe” function by wrapping up
product inside a function that will
trap the raised exception:
I thought this was really nice syntax, and got me thinking that we could use a
function in ramda that would wrap exceptions and let the composition keep
rolling along. One approach to doing that is to use a data type like
Either to wrap up the value. That is fine for some cases, but it means you will be
map-ping the rest of the way down your composition. That may be overdoing it
So I added a simple function
tryCatch evaluates the first function (i.e.
a -> b). If it does not throw, it
b. If it does throw, then the second function catches the exception.
It is evaluated with the thrown
Error and the original arguments, and must return
something of type
b. Et voila! You can compose with exceptions.
05 February 2016
tryCatch will be introduced in ramda 0.20.