簡體   English   中英

Clojure宏在調用時拋出“CompilerException java.lang.IllegalStateException:Var clojure.core / unquote is unbound”

[英]Clojure macro throws “CompilerException java.lang.IllegalStateException: Var clojure.core/unquote is unbound” when called

我正在嘗試編寫一個clojure宏,它允許我調用一個函數並使用提供的鍵值從map / struct中檢索參數,例如:

   (with-params  {:apple 2 :banana 3 :cherry 7} + :apple :banana)
   ;; 5

但是當我嘗試使用我寫的宏時:

(defmacro with-params [s f & symbols]
  `(~f ~@(map ~s ~symbols)))

調用

   (with-params  {:apple 2 :banana 3 :cherry 7} + :apple :banana)

給我

#<CompilerException java.lang.IllegalStateException: Var clojure.core/unquote is unbound. (NO_SOURCE_FILE:0)>

有人可以幫助我理解語法引用如何在這里工作嗎?

對於它的價值,無論如何這不應該是一個宏。 函數非常強大,只有當map和關鍵字都以編譯時文字形式給出時,宏版本才有效。

(defmacro with-params-macro [s f & symbols]
  `(~f ~@(map s symbols)))

(defn with-params-fn [s f & symbols]
  (apply f (map s symbols)))

user> (with-params-macro {:x 1} (fn [z] z) :x)
1
user> (let [params {:x 1}] 
        (with-params-macro params (fn [z] z) :x))
nil

user> (let [params {:x 1}] 
        (with-params-fn params (fn [z] z) :x))
1

`(~f ~@(map ~s ~symbols))不起作用的原因是編譯器在unquote-splicing~@ )內部對不必要的unquote~ )進行choke。 unquote-splicing取消syntax-quote外部syntax-quote` ),因此內部兩個unquote s沒有任何匹配的syntax-quote ,這就是你得到“未綁定”錯誤的原因。

你想要做的是首先評估(map s symbols)以得到操作數序列,然后將展平結果傳遞給函數( ~f ); 因此正確的版本是:

(defmacro with-params [s f & symbols] `(~f ~@(map s symbols)))

您可以使用以下方法輕松驗證:

(macroexpand '(with-params {:a 1 :b 2 :c 5} * :a :b :c))    ;; (* 1 2 5)
(with-params {:a 1 :b 2 :c 5} * :a :b :c)                   ;; 10

暫無
暫無

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

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