Clojure 如何编译在 REPL 中运行的代码?

Ask*_*ker 3 compilation clojure read-eval-print-loop

诚实的菜鸟问题。根据 Russ Olsen 的Getting Clojure,我知道以下内容:

(1) Clojure代码在运行前被编译为JVM字节码。

(2) Clojure 代码可以在 REPL 中运行,并且几乎可以立即得到反馈,该 REPL 使用函数 (read) 和 (eval) 或等效函数。

因此,Clojure 代码到 JVM 字节码的编译似乎必须在 REPL 期间的某个时刻发生,大概是在(读取)阶段或此后不久。

但这是一个模糊的心理画面,我想澄清一下。

例如,最好知道 REPL 中的代码何时实际被编译、编译创建的数据如何存储在 RAM中然后由 (eval) 访问,以及其间或此后发生的任何重要步骤。

换句话说,我想更详细地了解香肠的真正制作方法:

Clojure 如何编译在 REPL 中运行的代码?

(加分点:这与 Clojure 从非 REPL 源(例如 Leiningen 项目)编译代码时的做法有何不同?)

ama*_*loy 5

读取器使用字符并生成 Clojure 数据结构(列表、向量、符号等)。读取阶段肯定不知道有关 JVM 字节码的任何信息。这是 eval 阶段的一部分:编译器使用这些数据结构并生成 JVM 字节码。

运行 REPL 时,该字节码存储在 DynamicClassLoader 中 - 所有 JVM 类都必须由某个 ClassLoader 定义,而 DynamicClassLoader 是 Clojure 创建的,允许从 Clojure 数据结构动态定义类。

编译为类文件时,相同的字节码只是以 .class 文件形式写入磁盘,然后可能打包到 jar 中。