7

練習のために、私は定義しました

(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" が発生します。私が見逃している微妙なものはありますか?

4

1 に答える 1

3

前に構文引用符がありません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> 
于 2012-10-09T18:36:36.757 に答える