Macros 克洛朱尔的快乐,宏

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)

我一直在体验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)
                      (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)