I was working on a Tic-Tac-Toe game and needed to validate some user input. My function ended up getting quite large, and I had some error checking that was really irrelevant to the main idea of the function.

With many languages there’s usually a try-catch method to help with these sort of things, and Clojure is no exception.

Clunky Error Checking

The function’s purpose is to verify that only two numbers (representing a row and column) are received as input and that the cell that they reference holds the value, zero.

(defn valid-move? [board options]
  (let [size (count board)
        [row col] options]
    (and (= 2 (count options))
         (<= 0 row)
         (<= 0 col)
         (> size row)
         (> size col)
         (zero? (nth (nth board row) col)))))

As you can see, I have a lot of error checking here to ensure that row and col are within the bounds of the board. I also take the size of the board, which is only used to help verify row and col.

And of course, this function is still error-prone. If a board is passed in with shorter sized rows than columns, we would still get an error.

Catching Errors

When checking for every possible scenario is impossible or cumbersome, try-catch is there to save the day!

Really, all I need is a function that checks the board’s row/column value and ensures there are only two values. in the user’s input. Something like this would be ideal:

(defn valid-move? [board [row col & rest]]
  (and (empty? rest)
       (zero? (nth (nth board row) col))))

Of course, that doesn’t handle out-of-bound inputs–this should return false in those scenarios. If we wrap this in Clojure’s try-catch logic, we get the final version!

(defn valid-move? [board [row col & rest]]
  (try (and (empty? rest)
            (zero? (nth (nth board row) col)))
       (catch Exception _ false)))

Using the try-catch method here, we only see the information that we actually care about: board, row, col, and the rest of the user input, if any. No ugly error checking and straight to the point!