Check balanced brackets Yes, I know we have a lot of these.

I'm new to Clojure, but not to lisps. After the recent (javascript?) parentheses-balancing Q, I decided to do an implementation in Clojure for practice with the language. (It also happened to make a nice accompaniment to my rant about students learning what is and isn't possible with regular expressions.)

I chose to use (reduce) over recursion mostly because I am a fan of letting functions do the work of creating loops and recursion for me, but in this case I am not sure how "elegant" I consider the :false handling.

Code

(ns parens)

(def str-&gt;chars (partial map identity))

(defn mk-balanced?
  "makes a balanced? checker from table, which maps closing characters to
  opening characters.

  see also: balanced?"
  [table]
  (fn [s]
    (let [opens (set (vals table))
          closes (set (keys table))]
      (empty?
        (reduce
          (fn [stack cur]
            (if (not= (peek stack) :false)
              (condp contains? cur
                opens (conj stack cur)
                closes (if (and (seq stack)
                                (= (peek stack) (table cur)))
                         (pop stack)
                         [:false])
                stack)
              [:false]))
          []
          (str-&gt;chars s))))))

(def balanced?
  (mk-balanced? {\) \(
                 \] \[
                 \} \{}))
I'd never thought of using reduce for this. Neat! However, you can simplify mk-balanced? a little. 


str-&gt;chars is redundant: reduce and the other sequence functions accept strings as such.
You can use reduced to short circuit a reduce.
The reduced can return any non-empty sequence: no need for [:false].


The simplified version is ...

(defn mk-balanced? [table]
  (fn [s]
    (let [opens (set (vals table))
          closes (set (keys table))]
      (empty?
        (reduce
          (fn [stack cur]
            (condp contains? cur
              opens (conj stack cur)
              closes (if (and (seq stack)
                              (= (peek stack) (table cur)))
                       (pop stack)
                       (reduced [nil]))
              stack))
          []
          s)))))