> 但执行应该从`-main`方法开始,对吗?
是的,主要的执行功能是。运行所有的`ns`和`def`形式也是执行。运行任何其他类型的高级代码也是执行。Clojure的编译和执行是交织在一起的 —— 它与许多其他语言处理事情的方式不同。这也是为什么我们有很好的REPL体验,其中“E”部分与一开始就在某些uberjar中有相同代码的效果不可区分。反过来——在正常情况下运行编译好的组件将与通过REPL正常运行原代码的效果相同,一场场按顺序进行。
> 为什么变量会被重新绑定?
它们并没有被重新绑定。它们只是被绑定。uberjar编译过程和使用该uberjar的过程是两个不同的过程,运行相同的变量的两个不同的运行时版本。这与变量的值无关。
也许本节中的第二段会有所帮助:
https://clojure.org/reference/evaluation
> 比如说,我在计算第n个斐波那契数,这需要几秒钟。为什么我需要在编译和运行时都支付这种成本?
首先,计算任何N的斐波那契数不应该需要几秒钟。 :) 当然,这并不重要。
"为什么"这个问题没有一个直接的答案,因为这并不是一个像“是的,必须支付两次成本,用户必须忍受”这样的故意决定。这只是Clojure编译/评估方法的必然结果。
绝大多数情况下,此类事情完全可以不予理会,因为所有顶级代码都是纯函数式的`def`,计算时间并不明显。
如果某些非常特定的情况下不适用,我已提及了解决方案 - `delay` 和宏。