After spending a good deal of time trying to get my head around macros, I’ve finally created something vaguely useful – haskell-style guarded functions! I am pleased with how succinct this sort of expression-rewriting can be. Note – there is no reason to use this instead of ‘cond’, it is purely a learning exercise.

(defn generateGuardBody
	"Generates the function body required to support the guard macro"
	(let [[thisBranch remainingBranches] (split-at 2 args)
			testCond (first thisBranch)
			testResult (second thisBranch)
			elseFunc (if (empty? remainingBranches)
				(if (=  1 (count remainingBranches))
					(first remainingBranches)
					(generateGuardBody remainingBranches)))]
		`(if ~testCond

(defmacro defguardfn
	"Creates a haskell-style guarded function"
	[fnName args & body]
	`(defn ~fnName ~args
		~(generateGuardBody body)))

(defmacro guard
	"Allows inline guard syntax without surrounding defn"
	[& body]
	`~(generateGuardBody body))

(defguardfn testFn [n]
	(= 1 n) "You entered 1!"
	(= 2 n) "You entered two!"
	(= 3 n) "You entered three!"
	(> n 3) "You entered a big number!")

(println (testFn 5))

(defguardfn fib [n]
	(< n 2) n
	(+ (fib (- n 1)) (fib (- n 2))))

(defn testFn-2 [x]
		(= x 1) "One!"
		(= x 2) "Two!"
		true  "Something Else!"))

(println (map fib (range 0 10)))
(println (testFn-2 3)) ; "Something else!"