Not so difficult: as usual with such evaluators, you have two cases that you need to distinguish: self-evaluation of values and calls (application-function).
(defn evaluate [expression] (if (seq? expression) ;any sequence is a call with the operator in the first position (evaluate-call expression) expression))
Call evaluation is performed by first evaluating the operands / arguments. If one of them is a challenge in itself, we get the sequence back. In the first position of this sequence will be - by induction - the result of the expression (since it has already been evaluated).
(defn evaluate-call [expression] (let [arguments (map evaluate (rest expression))] ; evaluate arguments (cons (apply (get *functions* (first expression)) ; get function to apply (map #(if (seq? %) (first %) %) arguments)) ; extract result from evaluated result, if neccessary arguments)))
Finally, we put our result in sequence along with the arguments (evaluated) (this is what cons does).
Of course, we also need to determine the available functions:
(def ^:dynamic *functions* {'+ + '- - '* * '/ /})
Running this code in CIDER (sorry, I can not get ideone to work with clojure code):
evaluating.core> (evaluate '(* (+ 10 (* 4 9)) (- 6 10))) ;;=> (-184 (46 10 (36 4 9)) (-4 6 10))
source share