您可以覆盖宏和函数。例如:
(defn classic-lisp [arg]
(if (seq? arg) (seq arg) arg))
(defn = [& args]
(apply clojure.core/= (map classic-lisp args)))
(defmacro when [cond & args]
`(when (classic-lisp ~cond) ~@args))
不幸的是,您不能覆盖 if,因为它是一种特殊形式而不是宏。您将不得不用另一个宏包装您的代码。
让我们将 if* 宏设为具有 common-lisp 行为的 if:
(defmacro if* [cond & args]
`(if (classic-lisp ~cond) ~@args)
有了这个,我们可以用 if*s 替换所有的 if:
(use 'clojure.walk)
(defn replace-ifs [code]
(postwalk-replace '{if if*} (macroexpand-all code)))
(defmacro clojure-the-old-way [& body]
`(do ~@(map replace-ifs body)))
现在:
=> (clojure-the-old-way (if '() :true :false) )
:false
您也应该能够加载文件并替换其中的 ifs:
(defn read-clj-file [filename]
;; loads list of clojure expressions from file *filename*
(read-string (str "(" (slurp filename) ")")))
(defn load-clj-file-the-old-way [filename]
(doseq [line (replace-ifs (read-clj-file filename))] (eval line))
请注意,我没有测试加载文件的代码,它可能与 leiningen 或命名空间不兼容。我相信它应该与 overriden = 一起使用。