【问题标题】:Why does time need to be a macro?为什么时间需要是一个宏?
【发布时间】:2021-12-25 16:07:44
【问题描述】:

Clojure source code 给出了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#))

为什么这需要是一个宏?用函数做不到怎么办?

【问题讨论】:

    标签: time clojure macros


    【解决方案1】:

    因为函数在开始使用它们之前会评估它的参数。您可以将time 写为函数并尝试调用它:

    (defn my-time [expr]
      (let [start (System/nanoTime)
            ret expr]
        (prn (str "Elapsed time: " (/ (double (- (System/nanoTime) start)) 1000000.0) " msecs"))
        ret))
    
    (my-time (Thread/sleep 1000))
    "Elapsed time: 0.005199 msecs"
    => nil
    

    time 宏比较:

    (time (Thread/sleep 1000))
    "Elapsed time: 1000.1222 msecs"
    => nil
    

    函数 my-time 评估参数 (Thread/sleep 1000),符号 expr 得到值 nil 然后该函数的主体发生 - 两个 (System/nanoTime) 紧接着被调用,因为 expr 的值已经计算.

    time 未评估 (Thread/sleep 1000),但扩展为:

    (macroexpand `(time (Thread/sleep 1000)))
    =>
    (let*
     [start__6136__auto__ (. java.lang.System (clojure.core/nanoTime)) ret__6137__auto__ (java.lang.Thread/sleep 1000)]
     (clojure.core/prn
      (clojure.core/str
       "Elapsed time: "
       (clojure.core//
        (clojure.core/double (clojure.core/- (. java.lang.System (clojure.core/nanoTime)) start__6136__auto__))
        1000000.0)
       " msecs"))
     ret__6137__auto__)
    

    函数按以下顺序调用:(System/nanoTime)(Thread/sleep 1000) 和其他(System/nanoTime),返回正确的时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-09
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 2011-11-09
      • 2019-08-21
      • 2014-05-29
      相关资源
      最近更新 更多