为什么这个clojure函数不执行?

时间:2014-06-20 17:42:18

标签: macros clojure

我正在研究braveclojure的一些语言示例:

http://www.braveclojure.com/writing-macros/

目前我正在尝试执行此

(ns turtle (:use clojure.pprint))

(def criticisms {:good "good code:" :bad "bad code:"})

(defn criticize-code
    [[critkey code]]
    `(println (~critkey criticisms) (quote ~code)))

(defmacro code-critic
    [code-evaluations]
    `(do ~@(map criticize-code code-evaluations)))

(println "executed code critic")
(code-critic {:good (+ 1 1) :bad (1 + 1)})
(println "code critic expansion")
(pprint (macroexpand '(code-critic {:good (+ 1 1) :bad (1 + 1)})))

;why isn't this executing?
(println "criticize code expansion")
(criticize-code [:good '(+ 1 1)])

基本上,我可以验证批评代码通过println返回格式正确的代码;但我实际上无法执行它......有人可以告诉我我做错了吗?

谢谢!

1 个答案:

答案 0 :(得分:3)

正在调用函数criticize-code 。函数体中的准引号`是语法引用的读取器宏,这意味着在通过语法引用读取器之后,以下println形式将作为数据结构返回比执行。 criticize-code函数在语义上等同于

(defn criticize-code
  [[critkey code]]
  (list 
    'clojure.core/println 
    (list critkey 'turtle/criticisms) 
    (list 'quote code)))

如果您想将结果数据结构视为REPL中的代码,您可以直接eval

turtle=> (criticize-code [:good '(+ 1 1)])
(clojure.core/println (:good turtle/criticisms) (quote (+ 1 1)))
turtle=> (eval (criticize-code [:good '(+ 1 1)]))
good code: (+ 1 1)
nil

那么为什么你想要一个像这样工作的功能呢?作为宏的帮助者,就像code-critic一样。宏处理代码作为数据作为代码。因此,如果您坚持as-data阶段的辅助函数,则需要将其结果作为数据返回。否则,您要编译的代码只是在" compile"时间及其返回值(println返回nil)编译而来。