gpt4 book ai didi

clojure - try 和 catch 可以在不同的(但嵌套的)宏中吗?

转载 作者:行者123 更新时间:2023-12-02 18:55:53 24 4
gpt4 key购买 nike

try 位于一个宏中,catch 位于第二个宏中,由第一个宏调用。如何让以下内容发挥作用?

(defmacro catch-me []
`(catch ~'Exception ~'ex
true))

(defmacro try-me []
`(try (+ 4 3)
(catch-me)))

扩展try-me看起来不错:

(clojure.walk/macroexpand-all '(try-me))

产量

(try (clojure.core/+ 4 3) (catch Exception ex true))

但是调用(try-me)会产生:

"Unable to resolve symbol: catch in this context",

顺便说一句,这也是您在不尝试时使用 catch 时在 REPL 中收到的消息。

更新:

这就是我如何让它工作(谢谢,@Barmar),在这里你可以看到我的代码的实际上下文:

(defmacro try-me [& body]
`(try
~@body
~@(for [[e msg] [[com.mongodb.MongoException$Network "Database unreachable."]
[com.mongodb.MongoException "Database problem."]
[Exception "Unknown error."]]]
`(catch ~e ~'ex
(common/site-layout
[:div {:id "errormessage"}
[:p ~msg]
[:p "Error is: " ~e]
[:p "Message is " ~'ex]])))))

但这正是我所希望的(使用单独的宏catch-me):

(defmacro try-me [& body]
`(try
~@body
(catch-me com.mongodb.MongoException$Network "Database unreachable.")
(catch-me com.mongodb.MongoException "Database problem.")
(catch-me Exception "Unknown error.")))

我认为这会更容易编写/维护。

有什么想法吗?我需要语法引用,因为我正在传递参数,这就是为什么不幸的是亚瑟的答案无法应用(或者可以以某种方式应用吗?),但直到现在我才发布我的实际上下文。

最佳答案

您收到该错误的原因是 try 的语法是:

(try expr* catch-clause* finally-clause?)

这意味着在 catchfinally 子句之前可以有任意数量的 expr 形式。 try 扫描 expr 直到找到以 catchfinally 开头的表达式。它在扩展任何宏之前执行此操作,因为它只是试图找出 exprs 和 catch/finally 子句的开始位置。它收集所有 catchfinally 子句,并为它们建立适当的错误处理环境。

一旦执行此操作,它就会正常执行所有 expr 形式。因此它扩展了它们的宏,然后执行它们。但catch 不是函数或特殊形式,它只是try 在前面的步骤中查找的内容。因此,当它正常执行时,您会得到与在 REPL 中键入它时相同的错误。

您可能应该做的是编写一个宏,将整个代码包装起来,并将其扩展为您想要的 try/catch 表达式。如果没有您想要完成的任务的示例,就很难给出具体的答案。

关于clojure - try 和 catch 可以在不同的(但嵌套的)宏中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13129699/

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