> 但是执行应该从 `-main` 方法开始,对吧?
是的,执行 `_main` 功能。运行所有 `ns` 和 `def` 形式也是执行。运行任何其他类型的顶级代码也是执行。Clojure 的编译和执行是交织在一起的——这与许多其他语言处理方式不同。这就是我们拥有出色的 REPL 体验的原因之一,其中“E”部分与从一开始就在某个 uberjar 中拥有相同的代码难以区分。反之亦然——在正常情况下运行编译后的工件将与通过 REPL 逐行按正确顺序运行原始代码没有区别。
> 为什么变量会被重新绑定?
它们并没有被 _重新_ 绑定。它们只是被绑定。uberjar 编译过程和使用该uberjar的过程是两个不同的过程,它们有相同的 var 的两个不同的运行时版本。这与变量的值无关。
也许本节第二段会有所帮助:[链接](https://clojure.org/reference/evaluation)
> 举个例子,我正在计算某个第 n 个斐波那契数,这个过程可能需要几秒钟。为什么我既需要在编译时也需要在运行时付出这个代价?
首先,计算任何 N 的斐波那契数都不应该需要几秒钟。 :) 当然,但这不是重点。
关于“为什么”的问题没有简单的答案,因为这并不是一个像“是的,必须支付两次代价,用户必须忍受”这样的故意决定。这只是 Clojure 的编译/求值方法的后果。
绝大多数情况下,这类事情根本无关紧要,因为所有顶层代码都是简单的引用透明 `def`,其计算时间不明显。
如果某些情况下不是这样,我已经提到了解决方案——`delay` 和宏。