【发布时间】:2017-02-23 15:45:06
【问题描述】:
我正在通过 Clojure 为 Brave and True 工作。在关于宏的章节中有这个练习:
编写一个宏,使用一个宏调用定义任意数量的属性检索函数。你可以这样称呼它:
(defattrs c-int :intelligence
c-str :strength
c-dex :dexterity)
这些函数的作用是从映射中检索一个值。例如给定:(def character {:name "Travis", :intelligence 20, :strength 23, :dexterity 13})
(c-int character) 的结果是20 当然这样的函数可以很容易地定义为(def c-int #(:intelligence %))
这是我对这个问题提出的解决方案:
(defmacro defattrs
[& attributes]
`(let [attribute-pairs# (partition 2 (quote ~attributes))]
(map (fn [[function-name# attribute-key#]]
(def function-name# #(attribute-key# %)))
attribute-pairs#)))
我遇到的问题是def 使用生成的符号名称而不是它解析来定义函数的名称(考虑到def 的用法,事后看来这是有道理的)。我尝试使用具有定义函数的表达式,例如:
(let [x ['c-int :intelligence]]
(def (first x) #((second x) %)))
已导致此错误:CompilerException java.lang.RuntimeException: First argument to def must be a Symbol, compiling:(/tmp/form-init5664727540242288850.clj:2:1)
关于如何实现这一点的任何想法?
【问题讨论】: