Clojure, Python, and other modern programming languages lend themselves to the kind of code in which functions are called in all kinds of places, passed as parameters, returned from functions, and so on. In those instances, handling exceptions becomes tricky. It is not like the good old days of C/C++ coding, or at least today’s software seems less like those days.
Recently, while re-writing some Clojure code that depended on data extraction based on nth into functions that processed sequences of maps, I looked at the vulnerability of the new functions. They assumed the right data was being passed to them. I thought, well what if someone passes a sequences of vectors or lists?
The following functions show an example of what I needed and its solution. There is undoubtedly a better way to have done this, but at least this stops me dead in my tracks, so I can go fix a problem more easily.
(defn seq-of-maps? "Tests for a sequence of maps, and throws a custom exception if not." [s-o-m] (if-not (seq? s-o-m) (throw (IllegalArgumentException. "s-o-m is not a sequence")) (if-not (map? (first s-o-m)) (throw (IllegalArgumentException. "s-o-m is not a sequence of maps.")) true))) (defn ret-map-col "Selects a key from a sequence of maps using a map key." [in-key in-seq] (if (seq-of-maps? in-seq) (map (fn [x] (in-key x)) in-seq) nil))