在Clojure中嵌套语法引号中协调自动生成语法
在Clojure中,您需要使用在Clojure中嵌套语法引号中协调自动生成语法,clojure,gensym,Clojure,Gensym,在Clojure中,您需要使用gensym在宏中创建内部使用的符号,以保持它们的卫生。但是,有时需要在嵌套的语法引号中使用相同的符号。例如,如果我想用let将一个值绑定到一个符号,并在展开的循环中打印三次,我会这样做 `(let [x# 1] ~@(repeat 3 `(println x#))) 但这会产生 (clojure.core/let [x__2__auto__ 1] (clojure.core/println x_
gensym
在宏中创建内部使用的符号,以保持它们的卫生。但是,有时需要在嵌套的语法引号中使用相同的符号。例如,如果我想用let
将一个值绑定到一个符号,并在展开的循环中打印三次,我会这样做
`(let [x# 1]
~@(repeat 3
`(println x#)))
但这会产生
(clojure.core/let [x__2__auto__ 1]
(clojure.core/println x__1__auto__)
(clojure.core/println x__1__auto__)
(clojure.core/println x__1__auto__))
x#
在let
表单中生成的符号与嵌套在其中的println
表单中的符号不同,因为它们是从不同的语法引号中创建的
为了解决这个问题,我可以事先生成符号并将其插入到语法引号中:
(let [x (gensym)]
`(let [~x 1]
~@(repeat 3
`(println ~x)))
)
这将产生正确的结果,在所有地方都需要相同的符号:
(clojure.core/let [G__7 1]
(clojure.core/println G__7)
(clojure.core/println G__7)
(clojure.core/println G__7))
现在,虽然它确实产生了正确的结果,但代码本身看起来丑陋而冗长。我不喜欢必须“声明”一个符号,注入语法使它看起来像是来自宏外部,或者是在宏内部的某个地方计算出来的。我希望能够使用auto-gensym语法,它清楚地表明这些是宏内部符号
那么,有没有办法将auto-gensym与嵌套的语法引号一起使用,并使它们产生相同的符号?auto-gensym的符号仅在定义它们的语法引号内有效,并且它们不在无引号的代码中工作,因为这不是语法引号的一部分 此处符号
x 35;
被其gensym替换,因为它在以下语法引号的范围内:
core> `(let [x# 1] x#)
(clojure.core/let [x__1942__auto__ 1] x__1942__auto__)
core> `(let [x# 1] ~@x#)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: x# in this context, compiling:(NO_SOURCE_PATH:1)
如果您取消引用它,它将不再被转换为它的语法quote:
core> `(let [x# 1] x#)
(clojure.core/let [x__1942__auto__ 1] x__1942__auto__)
core> `(let [x# 1] ~@x#)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: x# in this context, compiling:(NO_SOURCE_PATH:1)
Auto gensym是语法引号中非常方便的快捷方式,在其他任何地方,您显然需要直接使用gensym
,后面的示例就是这样
还有其他方法可以构造此宏,因此AutoGenSym可以工作,尽管在Clojure和其他Lisp中,在宏顶部的let中声明gensymed符号是非常正常的。您的方法(调用gensym)是正确的
但是,在某些情况下,您可以巧妙地使用doto
、->
或->
。见:
`(let [x# 1]
(doto x#
~@(repeat 3 `println)))
谢谢我无法正常引用print表达式,但我想对于更复杂的宏来说,这将变得很麻烦……如果您这样做,我强烈建议使用'println,而不是'println-如果宏用户具有不寻常的名称空间或词汇上下文,则前者不受名称捕获的约束。@IdanArye抱歉,它不起作用,因为我的答案是错误的:-(我添加了一个希望正确的编辑我实际上考虑过使用
doto
,但没有找到命令-我在寻找类似于dowith
,因为这是我从其他语言中习惯的东西。。。