Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding optional argument to macro

Tags:

macros

clojure

I'm trying to add an option "message" attribute to the Clojure time macro. Basically I want to add an optional custom message to the output of time. I'm trying to find a bottleneck in my program and having some descriptive messages attached to time's output would be very helpful.

I've tried the following:

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

and

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

Both throw exceptions. How do I make this work?

like image 924
erikcw Avatar asked Oct 11 '22 04:10

erikcw


1 Answers

It throws an exception because msg is a list,

say you call it with,

(time (+ 1 1) "asd")

msg in the macro becomes a function call, ("asd") which fails. Just destructure msg,

 [expr & [msg]]

and use

 ~msg

You can also test how macros are expanded with macroexpand,

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

Also couple of points,

  • time is already in core
  • your version only accepts and times a single expression.

EDIT: time with optional message,


(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
like image 136
Hamza Yerlikaya Avatar answered Oct 20 '22 09:10

Hamza Yerlikaya