You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Clojure中的time需要实现为宏而不能用普通函数?

为什么Clojure的time要实现为宏

首先我们先看time的官方实现:

(defmacro time
  "Evaluates expr and prints the time it took.  Returns the value of
expr."
  {:added "1.0"}
  [expr]
  `(let [start# (. System (nanoTime))
         ret# ~expr]
     (prn (str "Elapsed time: " (/ (double (- (. System (nanoTime)) start#)) 1000000.0) " msecs"))
     ret#))

核心原因和普通函数无法实现的点,都和Clojure的求值规则、宏的编译期展开特性有关:

  • 求值时机可控:Clojure的普通函数遵循应用序求值,调用时会先把所有入参求值完成再传入函数体。如果time是普通函数,你调用(time (heavy-calc 10000))的时候,heavy-calc会先执行完得到结果再传给time,完全没法统计目标代码的执行耗时。而宏是在编译期把传入的表达式直接插入到展开后的代码里,我们可以在目标表达式执行前先打点,执行完再算耗时,刚好匹配计时的需求。
  • 无额外开销、计时更准确:宏是编译期展开,最终执行的代码和你手写计时逻辑的效果完全一致,没有额外的函数调用开销,统计出来的耗时更贴近实际执行时间。
  • 完全保留目标表达式的行为:宏展开后目标表达式是在调用方的词法上下文里执行的,表达式里用到的局部变量、外部绑定都能正常解析,而且可以原封不动返回目标表达式的执行结果,调用time完全不会影响原有代码的逻辑和返回值,用普通函数很难做到完全无侵入的效果。

内容的提问来源于stack exchange,提问作者J. Mini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 00:06:03