2014-12-08 72 views
2

可以說我有fn begin(begin "hello")`(begin "hello")的結果將爲(my-ns/begin "hello")。這很好。但現在我這樣做:(def x '(begin "hello"))。如何通過反引號擴展x以獲得(my-ns/begin "hello"),而不僅僅是(begin "hello")嵌套的報價和擴大

回答

3

在第一個示例中,您使用了`這是一個名爲「syntax-quote」的閱讀器宏,在第二個示例中,您使用了'這是一個名爲「quote」的閱讀器宏。語法引號提供超出quote提供了幾個特點:

  • ~[email protected] unquoting等
  • 符號命名空間擴展用於書寫衛生型宏。

普通老quote既不這些。因此,如果您希望兩個示例中的命名空間擴展在兩個地方都使用`。如果你想在語法列表中得到一個不帶名稱空格的符號,你可以將它們一起使用,其中`(println ~'symbol-name)將被評估爲(println symbol-name)。 (在這種情況下,符號名稱需要在調用它的名稱空間中定義(此過程稱爲「符號捕獲」))。語法引用首先對引用調用進行評估,然後依次評估符號。

如果您正在尋找擴大已經存在的某種原因一個符號,或者您想擴大它在幾個不同的命名空間,這兩個定義它,你可以使用ns-resolve功能:

(ns-resolve *ns* 'begin) 

所以在你比如你可以在列表上映射這與NS合格標誌打印:

user> (map #(if (symbol? %) (ns-resolve *ns* %) %) x) 
(#'user/begin "hello") 

雖然這不是正是所需的輸出,因爲它指的是VAR在南espace而不是解析爲此var的符號。由於`是一個閱讀器宏,我們無法在其他宏中調用它,所以在這裏有點冒險。舉例來說,我能想到的任何方式來寫:

(defmacro expand-x [thing] 
    `(syntax-quote-here ~thing) 

因爲據我所知語法的報價不具有名稱(又因爲它是一個閱讀器宏)所以沒有什麼地方使用上例中的語法引用。雖然從不畏懼,與eval沒有什麼語言是不可能的,事情就得到任意醜:

user> (eval (read-string (str "`" x))) 
(user/begin "hello") 

PS:不實際使用這個最後的例子或搗蛋鬼將居住在你的代碼的所有時間

+0

我想我誤解了你的問題。我會立即修復此問題 – 2014-12-08 07:05:32

+0

感謝您使用ns-resolve。我試圖知道如何將名稱空間映射到符號時,我將該窗體傳遞給宏:http://pastebin.com/0SHKh87r – zarkone 2014-12-08 07:59:29

+0

p.s.在這個特定的例子中,我可以使用'defn'而不是'def'來解決我的問題,謝謝#clojure IRC =) – zarkone 2014-12-08 08:00:43