Clojure文件编译的步骤是什么?

4

我很好奇当Clojure文件编译成类文件时实际上会发生什么。AOT编译文件时,宏的处理方式是什么?

在REPL评估和编译之间有什么区别吗?


2
无论是在AOT模式还是非AOT模式下,编译器本身都不会看到宏。编译后的代码也不会引用宏。reader会将提供的文本转换为嵌套形式的数据结构。每个宏调用表单都会被其值所替代,该值应该是另一个表单数据结构。这个过程一直持续到没有宏调用为止。最终的无宏结构将被提交给编译器本身。 - Thumbnail
1个回答

2
关于宏缩略图评论是正确的。 阅读器总是在任何其他事情之前首先评估宏,就像这样。
此乃某些事情可以作为宏而不是函数的原因。 例如:or 是宏的一个简单原因。让我们看看如何将 or 定义为宏或函数。
(defmacro or
  ([] nil)
  ([x] x)
  ([x & next]
      `(let [or# ~x]
         (if or# or# (or ~@next)))))


(defn or
  ([] nil)
  ([arg] arg)
  ([arg & args]
    (if arg arg (or args))

现在,假设你尝试使用(or 1 (println :foo))调用这两个函数。宏只会简单地返回1,而函数会返回1并打印“:foo”。以上情况通过上面的图片有所解释。读者首先通过重新构造扩展源代码,然后评估参数。函数首先评估参数,然后评估主体。编译成类将落在大约评估步骤附近。

1
我曾认为宏也是函数。如果我定义了一个宏,然后在同一命名空间中使用它,文件会如何编译? - zcaudate
宏不是函数,如上所述。您可以使用与函数相同的语法访问宏(这意味着您只需像 (foo x y) 一样调用它)。但是,每次使用宏并编译该文件时,宏都会在原地展开。为了扩大上面的例子:如果我在代码的任何地方调用 or 宏,则将其替换为宏主体和相应的参数。(余下的 or 将进一步展开,然后是剩余的 or,直到没有宏为止)http://pastebin.com/Ukx5NNCn - WeGi
宏定义怎么样?它们被编译了吗? - zcaudate
2
是的。宏定义编译成一种可通过名称在编译上下文中访问的形式转换函数。 - Thumbnail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接