gpt4 book ai didi

clojure - 在 Clojure 的嵌套语法引号中协调自动生成符号

转载 作者:行者123 更新时间:2023-12-03 20:23:35 25 4
gpt4 key购买 nike

在 Clojure 中,您需要使用 gensym在宏中创建供内部使用的符号,以保持它们的卫生。但是,有时您需要在嵌套语法引号中使用相同的符号。例如,如果我想用 let 将值绑定(bind)到符号上。并在展开的循环中打印三遍,我会这样做

`(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嵌套在其中的表单 - 因为它们是从不同的语法引号创建的。

为了解决它,我可以预先生成符号并将其注入(inject)到语法引号中:
(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))

现在,虽然它确实产生了正确的结果,但代码本身看起来既丑陋又冗长。我不喜欢必须“声明”一个符号,并且注入(inject)语法使它看起来像是来自宏外部,或者在其中某处计算。我希望能够使用 auto-gensym 语法,这清楚地表明这些是宏内部符号。

那么,有没有办法使用带有嵌套语法引号的 auto-gensym 并使它们产生相同的符号?

最佳答案

自动生成符号仅在定义它们的语法引用中有效,并且它们在未引用的代码中不起作用,因为这不是语法引用的一部分。

这里的符号 x#被它的 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)

自动生成符号是语法引用中非常方便的快捷方式,您显然需要在其他任何地方使用 gensym直接就像你后面的例子一样。

还有其他方法可以构造这个宏,因此 autogensyms 可以工作,尽管在宏顶部的 let 中声明 gensymed 符号在 Clojure 和其他 lisp 中也是非常正常的。

关于clojure - 在 Clojure 的嵌套语法引号中协调自动生成符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12676496/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com