【发布时间】:2012-11-06 04:46:20
【问题描述】:
假设我想定义一个名为 defsomething 的宏,这样:
(defspecial a x)
…扩展为:
(def a (f `a x))
语法引用`a 有一个棘手的部分。我看不出如何正确地将当前命名空间附加到符号上,使其表现得像语法引用。例如:
(defmacro defspecial [var-symbol expr]
`(def ~var-symbol (f '~var-symbol ~expr)))
(defspecial a x)
…扩展为:
(def a (f 'a x))
…很接近,但第二个 a 不是命名空间限定的。
我知道我可以使用*ns*:
(defmacro defspecial [var-symbol expr]
`(def ~var-symbol (f (symbol (name (ns-name *ns*)) (name '~var-symbol)) ~expr)))
……但我不喜欢那样;不仅丑,*ns* 是可重新绑定的,所以这是可能的:
(binding [*ns* (the-ns 'clojure.core)]
(defspecial a 5))
不幸的是,Clojure 显然没有syntax-quote 的` 形式,就像它有quote 的' 一样。那么,我应该如何最好地实现这个宏呢?
【问题讨论】:
-
` 不附加当前命名空间。如果没有给出你想要的例子以及它为什么不起作用的例子,很难理解你想要实现的目标(我的意思是,我知道你想在某处放置一个语法引用,我在说关于你的宏实际上应该做什么)。
-
背景是,这是一个将函数组合在一起制作解析器的库。一个更高级别的函数(称为
lbl)接受一个函数(称为p)并将其包装在另一个函数中,该函数为p返回的任何内容添加一种“标签”(用于解析函数的语法错误处理)。我想制作一个def的版本来定义解析器函数,我希望它自动调用函数上的lbl并用它们的变量名称标记它们。命名空间限定在这里会很好,因为我预计会有很多标签冲突。