2012-08-14 61 views
23

我正在学习Clojure宏,代码示例有时会具有构造'~symbol或者备选~'symbol。我知道(quote'阻止对表单进行评估,并且反引号还会添加名称空间限定,并且会导致对引用表单进行评估。我的问题是:为什么停止然后开始评估是有用的?我也假设~'symbol'~symbol是不同的,但是怎么样?Clojure中'〜'或'〜的用途是什么?

回答

30

~'symbol用于生成不合格符号。 Clojure的宏默认捕获名称空间,所以宏中的符号通常会被解析为(your-namespace/symbol)。 unquote-quote成语直接导致简单的,不合格的符号名称 - (symbol) - 通过评估引用符号。从喜悦的Clojure:

(defmacro awhen [expr & body] 
    `(let [~'it ~expr] ; refer to the expression as "it" inside the body 
    (when ~'it 
     (do [email protected])))) 

(awhen [:a :b :c] (second it)) ; :b 

'~symbol很可能用在宏或类似的东西插入一个名称。这里,symbol将被绑定到一个值 - let [symbol 'my-symbol]。然后通过评估symbol将此值插入到宏产生的代码中。

(defmacro def-symbol-print [sym] 
    `(defn ~(symbol (str "print-" sym)) [] 
    (println '~sym))) ; print the symbol name passed to the macro 

(def-symbol-print foo) 
(print-foo) ; foo 
+0

:)谢谢你,这是有道理的。 – Alex 2012-08-14 20:00:15

+0

还有一点我仍然不清楚:'(unquote(quote user/foo))'结果在'foo'而不是'user/foo',何时以及如何发生这种命名空间被剥离?它如何与评价以下形式的“unquote”的“正常”行为一致? – skuro 2012-08-15 07:32:53

+1

第一个示例不起作用。它应该是'\'(让[〜'it〜expr] ...' – Ming 2014-01-03 22:35:25

4

~unquote函数的阅读器宏。引用列表内它会导致一个符号,就能够评估而然后作为一个文字符号

user> (def unquoted 4) 
user>`(this is an ~unquoted list) 
(user/this user/is user/an 4 clojure.core/list) 
user> 

,除了不带引号的使用,就像不带引号的地方得到了解决它的4.该值的符号的符号一切最通常用于编写宏。当打印结果列表时,repl还会打印名称空间(用户)的名称。

许多宏,基本上只是模板,旨在做一些功能上无法完成的细微变化。在这个人为的例子中,模板宏通过调用def来定义一个函数。语法报价与unquoting使这更容易阅读:

user> (defmacro def-map-reducer [name mapper reducer] 
     `(defn ~name [& args#] 
       (reduce ~reducer (map ~mapper args#)))) 

#'user/def-map-reducer 
user> (def-map-reducer add-incs inc +) 
#'user/add-incs 
user> (add-incs 1 2 3 4 5) 
20 

相比:

user> (defmacro def-map-reducer [name mapper reducer] 
      (let [args-name (gensym)] 
       (list `defn name [`& args-name] 
        (list `reduce reducer (list `map mapper args-name))))) 

#'user/def-map-reducer 
user> (def-map-reducer add-decs dec +) 
#'user/add-decs 
user> (add-decs 1 2 3 4 5) 
10 
user> 
在第二个例子中

我也不要使用自动与gensyms功能,因为我在不语法引用

+0

所以我知道为什么我想在前面引用的列表中使用〜,我的问题是为什么我会使用〜'或'〜右边紧挨着。 – Alex 2012-08-14 19:35:34

+0

希望这个例子会显示更好的动机,谢谢你的反馈:) – 2012-08-14 21:28:54