2011-08-20 19 views
5

Próbuję dodać atrybut "wiadomość" opcji do makra czasu Clojure. Zasadniczo chcę dodać opcjonalny komunikat niestandardowy do wyjścia czasu. Próbuję znaleźć wąskie gardło w moim programie i posiadanie niektórych opisowych komunikatów związanych z wydrukiem czasu byłoby bardzo pomocne.Dodawanie opcjonalnego argumentu do makra

Próbowałem następujące:

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

i

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

Obydwa wyjątki rzut. Jak mogę to zrobić?

Odpowiedz

4

zgłasza wyjątek, ponieważ MSG jest lista,

powiedzieć nazywasz go,

(time (+ 1 1) "asd") 

MSG w makro staje się wywołanie funkcji ("asd"), który kończy się niepowodzeniem. Wystarczy destructure msg,

[expr & [msg]] 

i używać

~msg 

Można również sprawdzić, jak makra są rozwijane z macroexpand,

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

para także punktów,

  • czasową jest już w rdzeniu
  • Twoja wersja akceptuje tylko pojedyncze wyrażenie.

EDIT: razem z opcjonalnym wiadomości

 

(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 
+0

Używam wersji podstawowej, jednak w tym przypadku komunikat debugowania będzie bardzo pomocne dla mnie. Czy jest lepszy sposób to zrobić? Może jakieś makra otoki? Czy podstawowa wersja nie akceptuje tylko jednego wyrażenia? – erikcw

+0

@erikcw Tak, masz rację, moja zła podstawowa wersja akceptuje pojedynczy argument. dodano także wersję z opcjonalnym argumentem –