簡體   English   中英

麻煩的clojure引用-paren`(...)宏

[英]Trouble with clojure quote-paren `( … ) macro

對於練習,我已經定義了

(defmacro quote-paren
  "body -> `(body)"
  [& body]
  `(~@body))

它具有預期的轉換(quote-paren body) =>``(body)`。 它似乎滿足一些基本測試:

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"))

但是,我一直用這個do-while宏測試它(從這里修改):

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

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

但結果是

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

我不明白這一點,因為我可以看到`quote-paren'宏工作得很好(〜@ body插入):

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 clojure.core$test@1f07f672> (recur)))

但是嘗試宏擴展do-while會導致“ unbound fn ”。 有什么微妙的我不見了嗎?

quote-paren之前缺少語法引用

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

然后正確擴展:

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

似乎工作:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM