gpt4 book ai didi

macros - 使用宏创建记录

转载 作者:行者123 更新时间:2023-12-04 23:47:19 25 4
gpt4 key购买 nike

我有一条记录(defrecord Rec [id])

我喜欢用它

(def my ( Rec. 2 ))
(println (:id my))

现在我想用宏替换记录定义。这样我就可以写

(r 2) 
(println (:id my))

我写了宏

(defmacro r [id]
(list 'def 'my (symbol "(") 'Rec. id (symbol ")")))

我用macroexpand查了一下

(macroexpand-1 '(r 2))  => (def my ( Rec. 2 ))

但我在 (r 2) 上得到 RuntimeException: Too many arguments to def

最佳答案

从左括号创建符号与使用左括号计算文本不同。前者没有特别的意义;后者导致读取器生成一个嵌套列表,然后对其进行评估。

换句话说,Clojure 评估数据结构,而不是文本(或符号列表)。当您在 REPL 中键入内容时,该文本会被读入数据结构,然后对数据结构进行求值。

为了使其正常工作,宏需要自己生成一个嵌套列表:

(defmacro r [id]
(list 'def 'my (list 'Rec. id)))

或者更好的是,使用语法引号运算符:

(defmacro r [id]
`(def my (Rec. ~id)))

为了便于说明,您可以看到当 Clojure 代码被读取为文本时会发生什么:

(read-string "(def my (Rec. 2))")
=> (def my (Rec. 2))
(map type (read-string "(def my (Rec. 2))"))
=> (clojure.lang.Symbol clojure.lang.Symbol clojure.lang.PersistentList)

关于macros - 使用宏创建记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11766783/

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