> 但执行应该从"-main"方法开始,不是吗?
是的,主功能是执行的。运行所有`ns`和`def`形式也是执行。运行任何其他顶级代码也是执行。Clojure的编译和执行是相互交织的——这与许多其他语言处理方式不同。这是我们拥有出色的REPL体验的原因之一,其中“E”部分与从开始就在某个uberjar中有相同的代码难以区分。相反,在正常情况下运行编译后的工件将不会与通过REPL逐行按正确顺序运行原始代码不同。
> 为什么变量会重新绑定?
它们并不是真正的重新绑定。它们只是进行了绑定。uberjar编译过程和使用该uberjar的过程是两个不同的过程,各有不同的运行时版本的同一样变量。这与变量的值无关。
可能是本节第二段的内容有所帮助:
https://clojure.org/reference/evaluation
> 假设我正在计算第n个斐波那契数,这个过程需要几秒钟。为什么我需要在编译和运行时都付出这个代价?
首先,计算任何N的斐波那契数不应该需要几秒钟。 :) 但这已经偏离了重点,当然。
“为什么”这个问题没有直接的答案,因为这并不是一个像“是的,必须支付两次,用户必须忍受”这样的故意决策。这仅仅是因为Clojure的编译/评估方法的附带结果。
大部分时间,这类事情完全不重要,因为所有顶层代码都是简单的引用透明`def`,计算所需时间几乎没有。
如果由于某种原因,在非常具体的情况下不适用,我也提到了一些解决方案 - `delay`和宏。