gpt4 book ai didi

macros - Clojure 的宏——定义一个名称由参数组成的绑定(bind)

转载 作者:行者123 更新时间:2023-12-01 13:03:44 24 4
gpt4 key购买 nike

好的,我想写一个定义结构映射的 Clojure 宏,让调用者为每个字段指定类型。

签名看起来像这样:

(defmodel category :id Integer :name String)

它的作用是创建一个名为 category 的 struct-map,并创建一个绑定(bind) *category-meta*,这是一个映射 {: id 整数 :name 字符串}

这是我实现此目的的宏:

(defmacro defmodel [name & field-spec]
`(let [fields# (take-nth 2 ~@field-spec)]
(defstruct ~name fields#)
(def *~name-meta* (reduce #(assoc %1 (first %2) (last %2))) (partition 2 ~@field-spec))))

但是,问题是,我无法定义名称由另一个名称组成的绑定(bind)。基本上,(def *~name-meta* ...) 不起作用。

我怎样才能做到这一点?

谢谢。

最佳答案

(使用问题文本中宏的调试版本更新。)

这应该按规定工作:

(defmacro defmodel [name & field-spec]
`(do (defstruct ~name ~@(take-nth 2 field-spec))
(def ~(symbol (str "*" name "-meta*"))
(reduce #(assoc %1 (first %2) (last %2))
{}
(partition 2 '~field-spec)))))

主要问题的答案是使用 ~(symbol (str "*"name "-meta*")) 代替 *~name-meta*~ 取消引用语法引用形式的下一个表达式,将其返回值注入(inject)给定列表结构的适当位置。

一些其他的修改是必要的——特别是,defstruct 要求将键作为单独的参数提供给它,而不是单个 seq(或保存此类 seq 的变量的名称) , reduce 需要明确的种子值才能在这里工作等。

顺便说一句,除非您需要坚持使用 Clojure 1.1,否则您可能希望优先使用 1.2 的 defrecord 而不是 defstruct —— 事实上,后者已被弃用在 1.2 中。

关于macros - Clojure 的宏——定义一个名称由参数组成的绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4288360/

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