Error handling in clojure

I’m still not able to follow what problem you feel exceptions have that you would want solved?

I’m not really seeing any particular advantage to failjure, even after reading the article. I think its also really important to consider the full context of the programming language to understand why some use exceptions more so then returning error codes.

In Haskell for example, the first class support for Monad and all its supporting syntactic sugar makes it that returning an error code or the successful result does not result in unnecessarily verbose result handling code. You don’t need to have if a == Nothing then Nothing else ... everywhere every time you call any function that can fail. That’s because you’ll most likely compose the failing functions and their results using the monadic bind, which acts similarly to the Elixir with macro. But also, all execution is lazy, and so you can propagate the result back and pass it to other functions until one function actually needs to use it, only at that point must it handle the error case. Another benefit in Haskell is the type system will guarantee that you do not forget to check for error when it can have one, so by making the return type a sum type, you force error handling by the callers in a similar way that Java checked exceptions do (though I’d say a much nicer way, without the downfalls of checked exceptions.).

Yet, even with this, Haskell implemented a Exception mimicking monad, which behaves much like Java’s Exceptions apart for being implemented as a Monad, and thus benefiting from more syntax sugar then just the simple try/catch Java gives you. They did it so that you can attach much more context to errors, like a full stack trace, line numbers, and can support multiple exception out of a function and do conditional handling based on their type.

Another example is Elixir, as we saw earlier on. In Elixir, its the first class pattern matching and all its syntactic sugar which helps make the use of returning a tuple not overly verbose in a similar vain. Yet it can still result in quite a bit of boilerplate. Now things become complicated in Elixir, sometimes you pattern match on failure, sometimes you rescue exceptions, sometimes you try/catch values to fork control flow in a goto style, sometimes you let the supervisor restart the process. And thus, many questions and blog posts were written about how the hell do you deal with exceptions and errors in Elixir? In practice, its not that hard, but it does get confusing.

Now lets look at Clojure. Clojure extends Java, and must therefore deal with it (a curse and a blessing). So obviously, if the function chain includes some Java, you’ll need to deal with Java throwing exceptions, and your only option is to catch them to handle them. Clojure discards checked exceptions though, in that you do not need to declare your thrown exceptions (an improvement in my opinion).

When it comes to Clojure’s Clojure code it actually uses multiple strategies. Often times, it returns garbage instead when taking garbage. That is, it tries to just work no matter the input and return some form of output. In other cases, it returns nil or the value, in a pseudo Maybe style. Sometimes, Clojure does return pseudo Either, like with Vars, they can be unbound or bound. The rest of the time it throws exceptions.

Since Clojure does not have first class pattern matching, or monad, I think it would be too cumbersome to adopt a pattern of returning error codes from functions, and so Exceptions seem like a much better candidate.

So what I’m getting at is that Haskell had first class monads, and thus built its exception mechanism on it. Elixir had first class pattern matching, and thus built its exception mechanism on it. Clojure had first class exceptions, and thus built its exception handling mechanism on it.

So which style is best?

I don’t think any style wins out personally. I think people have the impression “Exceptions” are bad, but they are simply recounting what they’ve heard without understanding what, why and when. Most criticism of Java exceptions come from people disliking the CheckedExceptions. This is not an issue in Clojure. That’s why I’m trying to push towards discussing practical issues, such as, I want to do this, and I can’t, or I can but it seems overly verbose and makes the code confusing. Only then can you really be justified to say, I need a library to handle this error case in a simpler way, keeping the code short and readable.

9 Likes