То, что вы описываете, - это почти точно семантика оценки выражений в clojure :-), поэтому краткий ответ - запустить код :-D, хотя я подозреваю, что вы ищете более интересный ответ.
Вот простая рекурсивная версия, которая работает
- рекурсивно упрощает каждое вложенное выражение
- применяет правила упрощения к существующему выражению
Здесь в качестве примера используется слишком простое правило:
user> (defn my-eval [e]
(let [expanded-form (if (seq? e)
(map (fn [i]
(if (seq? i) ;; if this is a sequence,
(my-eval i) ;; eval the sequence and include the result here
i)) ;; otherwise use the value unchanged.
e)
e)] ;; if it's not a seq with something in it, leve it unchanged
(if (and
(seq? expanded-form)
(= (first expanded-form) 'or)
(= 2 (count (remove false? expanded-form))))
(second (remove false? expanded-form))
expanded-form)))
#'user/my-eval
Сначала тест базового случая:
user> (my-eval '(or x (or y false)))
(or x y)
Затем с небольшой рекурсией:
user> (my-eval '(or (or x false) (or y false)))
(or x y)