(defmacro arith [& args]
(letfn [(res [v]
(cond
(vector? v) (apply arith-body v)
(list? v) (map res v)
:else v))
(arith-body [s & args]
(reduce (fn ([expr] expr) ([expr [op arg]] `(~op ~expr ~(res arg))))
(res s)
(partition 2 args)))]
(apply arith-body args)))
(defn deriv [f]
(let [dx 0.001]
(fn [x] (arith
(f [x + dx]) - (f x) / dx))))
((deriv (fn [x] (arith x * x))) 3)
Another common problem is the piping of results from one function to the next: (f
(g
(h a)))
where you usually want to start reading the code in the lower rightmost corner and go upwards towards the left. Very messy in many lisps.Clojure has solved that problem with the threading macros, yielding postfix notation when you need it the most:
(-> a h g f)
Piping subresults between functions really doesn't get much better in any language.And that's of course some of the appeal of Lisp: The syntax may start controversial, but you can choose most of it yourself and make it depend on the problem, your tastes and of course, your readers.