我正在研究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
返回格式正确的代码;但我实际上无法执行它......有人可以告诉我我做错了吗?
谢谢!
答案 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
)编译而来。