向宏添加可选参数

eri*_*kcw 5 macros clojure

我正在尝试向Clojure时间宏添加一个选项"message"属性.基本上我想在时间输出中添加一个可选的自定义消息.我试图找到我的程序中的瓶颈,并在时间的输出上附加一些描述性消息将非常有帮助.

我尝试过以下方法:

;optional argument
(defmacro time
  "Evaluates expr and prints the time it took.  Returns the value of
 expr."
  {:added "1.0"}
  [expr & msg]
  `(let [start# (. System (nanoTime))
         ret# ~expr]
     (prn (str "Elapsed time: " (/ (double (- (. System (nanoTime)) start#)) 1000000.0) " msecs. " (first ~msg)))
     ret#))
Run Code Online (Sandbox Code Playgroud)

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

两者都抛出异常.我该如何工作?

Ham*_*aya 4

它抛出异常,因为 msg 是一个列表,

说你用它来称呼它,

(time (+ 1 1) "asd")
Run Code Online (Sandbox Code Playgroud)

宏中的 msg 变成函数调用(“asd”),该函数调用失败。只是解构消息,

 [expr & [msg]]
Run Code Online (Sandbox Code Playgroud)

并使用

 ~msg
Run Code Online (Sandbox Code Playgroud)

您还可以使用 Macroexpand 测试宏如何扩展,

(macroexpand '(time (+ 1 1) "asd"))
Run Code Online (Sandbox Code Playgroud)

还有几点,

  • 时间已经在核心
  • 您的版本仅接受并计算单个表达式。

编辑:带有可选消息的时间,


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

(time (+ 1 1))
"Elapsed time: 0.068 msecs. "
2

(time (+ 1 1) "asd")
"Elapsed time: 0.067 msecs. asd"
2
Run Code Online (Sandbox Code Playgroud)