> 但执行应该从`-main`方法开始,不是吗?
主功能的执行是这样。运行所有`ns`和`def`形式也是执行。运行任何其他顶级代码也是执行。Clojure的编译和执行是交织在一起的 - 它不同于许多其他语言的处理方式。这也是我们在REPL中有很好的体验的原因之一,那里的"E"部分和一开始就在某个uberjar中有相同代码的体验是一样的。反之亦然 - 通常情况下运行编译后的工件将与通过REPL逐个形式运行原始代码没有区别。
> 为什么变量会被重新绑定?
它们没有被重新绑定。它们只是被绑定。uberjar编译过程和使用该uberjar的过程是两个不同的过程,具有相同的变量的两个不同的运行时版本。这与变量的值无关。
也许本节的第二段会有所帮助:
https://clojure.org/reference/evaluation
> 假设我在计算some nth斐波那契数,这需要几秒钟。为什么我既要付出编译时的代价,也要付出运行时的代价?
首先,计算任何N的斐波那契数不应该需要几秒钟。 :) 但这无关紧要,当然。
"为什么"部分没有简单直接的答案,因为这并不是一个像“是的,必须支付两次代价,用户必须遭受痛苦”这样的故意决定。这仅仅是Clojure编译/评估方法的后果。
绝大多数情况下,这类事情完全不重要,因为所有顶级代码都是普通的引用透明(referentially transparent)的 `def` 形式,不需要计算就完成了。
如果由于某种原因,在特定情况下不是这样,我已提到有解决方案——`delay` 和宏(macros)。