2012-10-09 24 views
7

Dla praktyki, mam zdefiniowaneKłopoty z Clojure cytując-paren `(...) makro

(defmacro quote-paren 
    "body -> `(body)" 
    [& body] 
    `([email protected])) 

który ma oczekiwaną transformację (quote-paren body) =>` `(korpus)`. Wydaje spełniać kilka podstawowych badań:

user=> (macroexpand-1 `(quote-paren 3 4 5)) 
(3 4 5) 
user=> (macroexpand-1 `(quote-paren println "hi")) 
(clojure.core/println "hi") 
user=> (macroexpand-1 `(quote-paren (println "hi"))) 
((clojure.core/println "hi")) 

Jednak ja testuje go z tym zrobić, natomiast makro (modyfikowany here):

(defmacro do-while 
    [test & body] 
    (quote-paren loop [] 
    [email protected] 
    (when ~test 
     (recur)))) 

(def y 4) 
(do-while (> y 0) 
    (def y (dec y))) 

Ale wynik jest

IllegalStateException Attempting to call unbound fn: #'clojure.core/unquote-splicing clojure.lang.Var$Unbound.throwArity (Var.java:43) 

ja tego nie rozumiem, bo z tego co widzę macro `cytat-pAREN” działa prawidłowo (z ~ @ ciało podłączony):

user=> (macroexpand-1 
     `(quote-paren loop [] 
      (def y (dec y)) 
      (when ~test 
       (recur)))) 

(clojure.core/loop [] (def user/y (clojure.core/dec user/y)) (clojure.core/when #<core$test [email protected]> (recur))) 

Ale próby makroexpand do-while powoduje "unbound fn". Czy jest coś subtelnego, czego mi brakuje?

Odpowiedz

3

brakuje składni-quote przed quote-paren

user> (defmacro do-while 
    [test & body] 
    `(quote-paren loop [] 
    [email protected] 
    (when ~test 
     (recur)))) 
#'user/do-while 

który następnie rozszerza się odpowiednio:

user> (macroexpand '(do-while (> y 0) 
         (def y (dec y)))) 
(loop* [] (def y (dec y)) (clojure.core/when (> y 0) (recur))) 

i wydaje się działać:

user> (def y 4) 
#'user/y 
user> (do-while (> y 0) 
    (def y (dec y))) 
nil 
user> 
+1

i po prostu jako komentarz bocznej: using (def y ...), ponieważ kontrola pętli może mieć niezamierzone konsekwencje, które nie są związane z tym pytaniem ;-) –

+0

Hmm, masz rację, ale tego rodzaju pokonywa cel mojego ćwiczenia. Czy mimo to jest cytat-paren, który zastępuje '(quote-paren stuff)' z ''(stuff)'? Krótko mówiąc, niepotrzebne jest pisanie 'w definicji makra. – spacingissue

+0

Próbowałem zastąpić '(quote-paren stuff)' '(quote (stuff))' ale wydaje się, że przestaje rozpoznawać zmienne; że jest '(defmacro do-while [Test & body] (cytat (pętla [] ~ @ ciała (po ~ Test (powtarzać)))))' i działa wyników w 'CompilerException java.lang. RuntimeException: Nie można rozwiązać symbolu: body w tym kontekście, kompilując: (NO_SOURCE_PATH: 58) 'Jeśli jednak najlepiej poradzę sobie z innym pytaniem, zrozumiem. – spacingissue

Powiązane problemy