gpt4 book ai didi

Clojure 宏作为函数/​​ 'Partial' 用于宏?

转载 作者:行者123 更新时间:2023-12-04 21:20:39 25 4
gpt4 key购买 nike

这类似于 Treat Clojure macro as a function 中讨论的问题但是在尝试最佳答案中的方法时,我遇到了错误。希望关于我的特定应用程序的太多信息不是必需的,因为它非常复杂,但这里是我尝试做的事情的提炼版本:

(defmacro make-fn [m arg1] 
`(fn [& args#]
(eval `(~'~m ~'~arg1 ~@args#))))

我在这种情况下使用了宏:
(let [columns (make-columns table-width)
table-name (keyword (str "table_" n))]
(apply (make-fn helpers/tbl table-name) columns))

"helpers/tbl"是一个宏,它需要一个表名关键字和一个包含列规范(如 [:varchar 100] 或其他东西)的可变数量的列表。我正在尝试动态创建随机数据库表规范以方便一些测试。无论如何,在尝试执行上述代码时,出现以下错误:
CompilerException java.lang.RuntimeException: Unable to resolve symbol: table-name in this context, compiling:(NO_SOURCE_PATH:1) 

我有点理解这个问题:宏扩展是在编译时完成的,我试图在宏扩展中包含一个运行时值,因此奇怪地使用引用和取消引用来使一切设置得恰到好处。我基本上想要一个部分的宏,我需要能够对不同命名空间中的不同宏重用这种机制,并且所有的变量解析都正确。这甚至可能吗?

最佳答案

该问题是由 Clojure 在语法引用(反引号)表达式中解析符号的方式引起的。为了避免意外的变量捕获,Clojure 总是将语法引用表达式中的符号解释为引用 Vars(而不是局部变量)。

您可以通过“滚动您自己的”表单构建代码来解决这个问题,相当于由语法引用生成的代码。它和罪一样丑陋,但它有效……只是不要说我没有警告你:

(defmacro make-fn [m arg1]
(let [g (gensym)]
(list 'fn ['& g]
(list 'eval (list 'concat (list 'list m arg1) g)))))

哇,这就像我的 Common Lisp 时代的倒叙......

关于Clojure 宏作为函数/​​ 'Partial' 用于宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12589090/

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