2014-12-08 42 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