"Telling lies" in functional programming code


#1

Lately i’ve been reading about better error-handling and type checking in functional programming, specifically, in Clojure.

What i found out is that throwing exceptions and checking types or nulls, is considered as “telling lies” in functional code, things i do all the time both in PHP and in Clojure, since they are dynamic.

You can find a thread about it here, not the only place when people discuss about it though xD.

I’d love to know your take on this, are they correct? are these “rules” going to improve code maintainability? if so what tools can i use in Clojure in order to follow them. Personally i haven’t had the troubles they’ve with exceptions and type checking (guard clauses).


#2

Hey @kev93,

Thanks for the discussion!

In a typed language, it does seem like a lie to say “this function returns an integer” but then it throws an exception. I remember working in Haskell, there was a standard function called head that would give you the first element of a list. But what if the list was empty? It would throw an error. That was annoying behavior in that environment. It was obvious that it should never throw an error and instead return a Maybe. We define a function that did just that.

I think avoiding throwing exceptions and avoiding using nulls can improve maintainability. Exceptions mean you branch to handle them (the catch block of the try/catch). And nulls need to be checked (also a branch). These are branches that are not explicitly part of the model (represented by a type in certain languages). Exceptions and nulls are usually corner cases, which you typically want to avoid. They mean more code than necessary. Without corner cases, things compose more cleanly.

You can do the same in Scala, and many people do. And as he mentioned, you can do everything but nulls in Haskell. What Clojure doesn’t have that Scala and Haskell do are explicit calling out of effects.

I’ve heard of people being in favor of never throwing exceptions, especially for things that should be predictable. For instance, reading in a file that doesn’t exist. Is that truly exceptional? No, it’s actually common. It should be part of the explicit failure modes. True exceptions are rare, such as a failure of the runtime. OutOfMemoryError might be one of them.

Rock on!
Eric