何时在Clojure Macro中使用〜'some-symbol?

Ert*_*tin 2 lisp macros functional-programming clojure clojurescript

当我阅读Clojure的喜悦时,我遇到了一些代码.

(fn [~'key ~'r old# new#]
                  (println old# " -> " new#)
Run Code Online (Sandbox Code Playgroud)

这个声明的确切行为是什么〜'某些符号.

某些符号#和'~aother-symbol或gensym之间的区别?

Clojure的喜悦:(不明白)

你会在Clojure宏中看到模式〜'符号,用于有选择地捕获宏体中的符号名称.这种尴尬[11]的原因是Clojure的语法引用试图解析当前上下文中的符号,从而产生完全限定符号.因此,〜'通过不引用引号来避免该解决方案.

Ala*_*son 5

您可以在Tupelo库中看到带有Literate Threading Macro的示例.我们希望用户键入符号it并让宏识别它.这是定义:

(defmacro it->
  "A threading macro like as-> that always uses the symbol 'it' 
   as the placeholder for the next threaded value "
  [expr & forms]
  `(let [~'it ~expr
         ~@(interleave (repeat 'it) forms)
         ]
     ~'it))
Run Code Online (Sandbox Code Playgroud)

这也被称为"照应"宏.然后用户创建如下代码:

(it-> 1
      (inc it)                                  ; thread-first or thread-last
      (+ it 3)                                  ; thread-first
      (/ 10 it)                                 ; thread-last
      (str "We need to order " it " items." )   ; middle of 3 arguments
;=> "We need to order 2 items." )
Run Code Online (Sandbox Code Playgroud)

用户it在其代码中包含特殊符号,宏是期望的(在这种情况下是必需的).

这是一个特例.在大多数情况下,无论用户选择什么符号,您都希望宏工作.这就是为什么大多数宏使用(gensym...)或带有"#"后缀的阅读器版本,如下例所示:

(defmacro with-exception-default
  "Evaluates body & returns its result.  In the event of an exception, default-val is returned
   instead of the exception."
  [default-val & body]
  `(try
     ~@body
     (catch Exception e# ~default-val)))
Run Code Online (Sandbox Code Playgroud)

这是"正常"情况,其中宏创建"局部变量" e#,保证不与任何用户符号重叠.一个类似的例子显示spyx宏创建一个名为spy-val#临时保存评估表达式结果的"局部变量" expr:

(defmacro spyx
  "An expression (println ...) for use in threading forms (& elsewhere). Evaluates the supplied
   expression, printing both the expression and its value to stdout, then returns the value."
  [expr]
  `(let [spy-val# ~expr]
     (println (str (spy-indent-spaces) '~expr " => " (pr-str spy-val#)))
     spy-val#))
Run Code Online (Sandbox Code Playgroud)

请注意,对于(println...)语句,我们看到相反的语法'~expr- 但这是另一天的主题.