宏迭代未定义的符号

发布于 2024-11-28 13:33:54 字数 463 浏览 0 评论 0原文

当与另一个宏多次应用一个宏时,裸符号不会插入到当前上下文中:

(defmacro ty [type]
  `(deftype ~type []))

(defmacro empties [& args]
  (doseq [arg args]
    `(ty ~arg))
  )

(empties Base Person Animal)
;equivalent to:
;(ty Base)
;(ty Person)
;(ty Animal)


(derive ::Person ::Base)
(derive ::Animal ::Base)
(ty Me)
(prn ::Me)
(prn Me)
(empties Empty)
(prn ::Empty)
(prn Empty)

最后一行给出:“无法解析符号:此上下文中为空”,即使在使用直接宏 ty 时,它也有效。有办法解决这个问题吗?如果可以不用 eval 就更好了。

When applying a macro multiple times with a another macro, bare Symbols are not inserted into the current context:

(defmacro ty [type]
  `(deftype ~type []))

(defmacro empties [& args]
  (doseq [arg args]
    `(ty ~arg))
  )

(empties Base Person Animal)
;equivalent to:
;(ty Base)
;(ty Person)
;(ty Animal)


(derive ::Person ::Base)
(derive ::Animal ::Base)
(ty Me)
(prn ::Me)
(prn Me)
(empties Empty)
(prn ::Empty)
(prn Empty)

The last line gives: "Unable to resolve symbol: Empty in this context", even though when using the direct macro ty, it works. Any way to solve this? If possible without eval it would be much better.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

已下线请稍等 2024-12-05 13:33:54
(defmacro empties [& args]
  (doseq [arg args]
    `(ty ~arg)))

(empties Base Person Animal)
;equivalent to:
;(ty Base)
;(ty Person)
;(ty Animal)

这是错误的。您的 empties 调用意味着 empties 的宏扩展函数获取符号 BasePerson 和 <代码>动物。然后,它对每个宏调用求值,但不返回任何内容,因为 doseq 始终返回 nil。因此,empties 调用的扩展代码为零。您需要从宏函数返回单个表单。您应该将多个表单包装到一个 do 中,并实际上将所有子表单返回给该表单:

(defmacro empties [& args]
  `(do ~@(map (fn [arg]
               `(ty ~arg))
              args)))
(defmacro empties [& args]
  (doseq [arg args]
    `(ty ~arg)))

(empties Base Person Animal)
;equivalent to:
;(ty Base)
;(ty Person)
;(ty Animal)

This is wrong. Your empties call means that the macro expansion function for empties gets as arguments the symbols Base, Person, and Animal. It then evaluates the ty macro call for each, but does not return anything, as doseq always returns nil. So, the expanded code from that empties call is nil. You need to return a single form from your macro function. You should wrap the multiple forms into a do, and actually return all the subforms to that:

(defmacro empties [& args]
  `(do ~@(map (fn [arg]
               `(ty ~arg))
              args)))
栩栩如生 2024-12-05 13:33:54

FWIW,我更喜欢编写@Svante 的解决方案,因为

(defmacro empties [& args]
  (cons `do
        (for [arg args]
          `(ty ~arg))))

它也非常接近您的 doseq 方法的结构。

FWIW, I prefer to write @Svante's solution as

(defmacro empties [& args]
  (cons `do
        (for [arg args]
          `(ty ~arg))))

which is also pretty close to the structure of your doseq approach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文