Personal Library

This is my personal Clojure library. There came a point where I had to admit I just think about some things imperatively and fighting that is just wasting time.

opar.clj

(ns opar
  "Owen's generic Clojure code that is not in any way project specific"
  (:require [clojure.pprint]))

(defmacro imperative
  "
  This macro allows for blocks of imperative code. It behaves like an advanced (do) loop, where each argument is evaluated.

  But to make matters more confusing, it supports 2 ternary options:

  :< - Binds RHS to the symbol on the LHS
  :? - If the first form is true, evaluate the (imperative) to the 2nd form.

  For example:

  (imperative
    a :< '(1 2 3) ; Binds to a
    (<= (count a) 3) :? nil ; Evaluates, because the test condition is true
    (println \"I can also print\") ; If the test condition wasn't true, would print.
    b :< (nth a 3) ; bind b
    [a b]
    )
  "
  [& forms]
  (cond
    ; Can't be a ternary clause.
    (< (count forms) 3)   `(do ~@forms)
    ; LHS of a :< ternary clause
    (= (second forms) :<) `(let [~(first forms) ~(nth forms 2)] (imperative ~@(nthrest forms 3)))
    (= (second forms) :?) `(if ~(first forms) ~(nth forms 2) (imperative ~@(nthrest forms 3)))
    ; Not a ternary clause. (do) and recurse
    :else                 `(do ~(first forms) (imperative ~@(rest forms)))
    )
  )

(def log-print (ref prn)) ;prn -> "1", 1 displayed differently

(dosync (ref-set log-print (fn [& args] (doall (map clojure.pprint/pprint args)))))
(dosync (ref-set log-print println))
(dosync (ref-set log-print prn))

(defn log [& args]
  (apply @log-print args)
  )