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