cfg*_*uss 2 macros function clojure
我想编写一个宏,sym-def该宏具有与特殊形式相同的行为,def但是使用(symbol "c"),例如,作为第一个参数。
我的第一步是
(def (symbol "c") 4)
Run Code Online (Sandbox Code Playgroud)
但这返回了错误First argument to def must be a Symbol。
我的第二步是
(eval `(def ~(symbol "c") 4))
Run Code Online (Sandbox Code Playgroud)
c在全球环境中成功将其定义为4。为什么第二步成功却第一步失败了?
最后,我尝试编写所需的宏
(def (symbol "c") 4)
Run Code Online (Sandbox Code Playgroud)
但这有一个“坏” macroexpand
(eval `(def ~(symbol "c") 4))
Run Code Online (Sandbox Code Playgroud)
以便
(defmacro sym-def [sym value] `(def ~sym ~value))
Run Code Online (Sandbox Code Playgroud)
失败,出现与我第一步相同的错误。
编写宏的正确方法是什么?
def不评估其第一个参数。想象一下,如果发生的话,将会造成混乱!你不会写
(def x 1)
Run Code Online (Sandbox Code Playgroud)
因为它首先会尝试求值x,而由于x尚未定义而失败!现在,由于它不评估其参数,因此很明显
(def (symbol "c") 4)
Run Code Online (Sandbox Code Playgroud)
不起作用,就像
(def 'c 4)
Run Code Online (Sandbox Code Playgroud)
不会。def要求其第一个参数为文字符号。您没有文字符号,因此无法使用def。
但是,存在一种较低级别的机制来与名称空间中的映射进行交互。在这种情况下,您需要clojure.core/intern:
(intern *ns* (symbol "c") 4)
Run Code Online (Sandbox Code Playgroud)
intern是一个普通函数,因此它会评估其所有参数,这意味着您可以用任何想要的疯狂方式来构造var名称。然后,它将给您的符号映射到所需值的变量添加到给定的名称空间。
| 归档时间: |
|
| 查看次数: |
134 次 |
| 最近记录: |