简单的线程宏实现

时间:2013-12-10 22:07:30

标签: clojure

对于clojure来说非常新,所以可能是一个noob问题,但在这里。所以我读到->宏将按顺序调用函数,我理解它是如何工作的。 (-> (+ 1 2) (* 10))导致30

但为什么不这样做呢?

(defn testing-> [a b]
  (list a b)
  first)

当调用first时,返回函数(testing-> "a" "b")而不是“a”。我在这里错过了什么?以错误的方式使用它?

2 个答案:

答案 0 :(得分:5)

->需要位于函数体内。对于以 - >结尾的函数来说,这不是魔术但实际上是一个名为->的宏,它接受一系列事情要做,并生成一个新的表达式,其中相同的东西嵌套在下一个内部:

(defn testing [a b]
  (-> [a b]
      list
      first))

在这个例子中,当 - >宏运行它会产生一个新的表达式,如下所示:

(defn testing [a b]
  (first (list [a b])))

再举一个例子,当您使用arguemnts ->调用(+ 1 2) (* 10)时,它会返回表达式(* (+ 1 2) 30),然后将其作为正常的Clojure代码进行评估。

PS:宏是一个函数,它接受Clojure表达式并产生另一个Clojure表达式。这些运行在编译周期的中间,你可以看到他们使用macroexpand-1函数做了什么。

答案 1 :(得分:3)

宏是在编译之前重构其输入的东西。

user> (macroexpand '(-> (+ 1 2) (* 10)))
(* (+ 1 2) 10)

testing->是一个函数,而不是宏,因此它不会重构输入。您需要在评估之前重新排列输入表单,以获得类似于->的行为。每个有效的表单都需要在编译时转换为标准的clojure语法,这是通过reader-expansion和macro-expansion完成的。

宏构造使用标准的Clojure函数,但语义有些独特(宏应该返回将在运行时使用的表单)。您可以使用clojure.repl/source宏来查看各种宏的实现方式。

您需要的任何操作都可以表示为函数,除非您需要新语法,否则应避免使用常规创建宏。