Cleaner Functions with Clojure’s :pre Special Form

In the course of programming, it’s fairly common to face a scenario where you want to ensure that a function’s arguments fulfil some condition(s), and if not, to throw an error. In this post, we’re going to see how Clojure provides a handy special form that greatly simplifies this task.

One such scenario that I’ve come across recently is trying to come up with a function that would compute the 3x + 1 problem (Collatz conjecture). The problem is as follows:

Take any positive integer n.

If n is even, divide n by 2 to get n / 2.

If n is odd, multiply n by 3 and add 1 to get 3n + 1.

Repeat the process indefinitely.

The conjecture states that no matter which number you start with, you will always reach 1 eventually.

The task at hand was to write a function that takes a number as an argument and returns the number of steps it takes for the number to eventually be 1.

You’ll also notice that the first condition for the number to be passed in is that it has to be a positive integer. Therefore, given any value less than 1, the function should throw an error.

A typical solution in Clojure would look as follows:

collatz-first
Collatz first try

While this definitely works, I found out that Clojure provides a much more elegant way to accomplish this, with the help of the :pre special form.

This form enables specifying conditions about the arguments that should be met before the rest of the function body is evaluated. If any of the conditions is not met, an assertion error is thrown.

This is how we could rewrite the function making use of the :pre condition:

collatz-with-pre
Collatz with :pre special form

In this case, if the function is called with 0 or a negative number, an assertion error is automatically thrown.

I think you would agree that the second version looks much nicer 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.