【问题标题】:Adding optional argument to macro向宏添加可选参数
【发布时间】:2011-08-20 19:18:44
【问题描述】:

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

我尝试了以下方法:

;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#))

(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#)))

两者都抛出异常。我该如何完成这项工作?

【问题讨论】:

    标签: macros clojure


    【解决方案1】:

    因为 msg 是一个列表,所以会抛出异常,

    说你叫它,

    (time (+ 1 1) "asd")
    

    宏中的msg 变成了一个失败的函数调用(“asd”)。只需解构 msg,

     [expr & [msg]]
    

    并使用

     ~msg
    

    您还可以使用macroexpand 测试宏是如何展开的,

    (macroexpand '(time (+ 1 1) "asd"))
    

    还有几点,

    • 时间已经到了核心
    • 您的版本只接受单个表达式并对其计时。

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

    (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
    

    【讨论】:

    • 我一直在使用核心版本,但是对于这种情况,调试消息对我真的很有帮助。有一个更好的方法吗?也许某种包装宏?核心版本不也只接受一个表达式吗?
    • @erikcw 是的,你是对的,我糟糕的核心版本也接受一个参数。还添加了一个带有可选参数的版本
    猜你喜欢
    • 2011-01-20
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-31
    • 1970-01-01
    • 2011-03-04
    相关资源
    最近更新 更多