Macros 克洛朱尔的快乐,宏
我一直在体验clojure练习的乐趣,遇到了这个例子Macros 克洛朱尔的快乐,宏,macros,clojure,symbols,Macros,Clojure,Symbols,我一直在体验clojure练习的乐趣,遇到了这个例子 (defn build-contract [c] (let [args (first c)] (list (into '[f] args) ;; here is where i am confused (apply merge (for [con (rest c)] (cond (= (first con) :require)
(defn build-contract [c]
(let [args (first c)]
(list
(into '[f] args) ;; here is where i am confused
(apply merge
(for [con (rest c)]
(cond (= (first con) :require)
(assoc {} :pre (vec (rest con)))
(= (first con) :ensure)
(assoc {} :post (vec (rest con)))
:else (throw (Exception. (str "Unkown tag " (first con)))))))
(list* 'f args)))) ;; and here
(defn collect-bodies [forms]
(for [form (partition 3 forms)]
(build-contract form)))
(defmacro contract [cg & forms]
(list* `fn cg (collect-bodies forms)))
我似乎不明白为什么你会想要在向量中有一个叫做f的符号。符号指的是事物,那么f指的是什么呢?为什么我们需要引用它?宏构建一个函数文本表达式(一个
fn
表单)
这是参数向量。f
在这里作为形式参数出现
(list* 'f args)))) ;; and here
这是一个函数应用程序f
是一个函数参数,这里它应用于args
构建时,生成的定义将如下所示
(fn name [f arg1 arg2] ... (f arg1 arg2))
符号实际上是对事物的引用,该特定宏正在构建一个函数,而符号
f
指的是该函数接收到的函数参数f
。(宏正在生成一个函数,该函数接收一个函数作为参数,名为f
)
在宏内部,当您需要引用命名参数时,这就是您的f
在这种情况下:
(into '[f] args)
同:
(into ['f] [a1 a2 a3])
它正在构建函数参数,如中所示
(fn cg [f a1 a2 a3] ...
最后一个调用只是函数调用
(f a1 a2 a3)
我手边没有一本Clojure的Joy,但我很惊讶他们没有使用
(gensym)
而不是限定的f
。如果一个arg
可以被称为f
,那么他们的代码可能会非常糟糕。@lgrapenthin也许这是该课程的第一步?
(f a1 a2 a3)