0dB*_*0dB 6 macros clojure try-catch
的try是在一个宏时,catch在由第一被叫的第二个.如何让以下工作?
(defmacro catch-me []
`(catch ~'Exception ~'ex
true))
(defmacro try-me []
`(try (+ 4 3)
(catch-me)))
Run Code Online (Sandbox Code Playgroud)
扩展try-me看起来很好:
(clojure.walk/macroexpand-all '(try-me))
Run Code Online (Sandbox Code Playgroud)
产量
(try (clojure.core/+ 4 3) (catch Exception ex true))
Run Code Online (Sandbox Code Playgroud)
但是打电话(试试我)产量:
"Unable to resolve symbol: catch in this context",
Run Code Online (Sandbox Code Playgroud)
BTW,这也是你在不尝试时使用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]])))))
Run Code Online (Sandbox Code Playgroud)
但这是我希望的(使用单独的宏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.")))
Run Code Online (Sandbox Code Playgroud)
我认为这会更容易编写/维护.
有任何想法吗?我需要语法引用,因为我传递参数,这就是为什么不幸的是亚瑟的答案不能应用(或者它可以以某种方式?),但我直到现在才发布我的实际上下文.
您收到该错误的原因是因为语法为try:
(try expr* catch-clause* finally-clause?)
Run Code Online (Sandbox Code Playgroud)
这意味着在catch和finally子句之前可以有任意数量的expr形式.扫描s直到找到以or 开头的那个.它在扩展任何宏之前执行此操作,因为它只是试图找出exprs和catch/finally子句的开始位置.它收集所有和子句并为它们建立适当的错误处理环境.tryexprcatchfinallycatchfinally
一旦这样做,它就会expr正常执行所有表单.所以它扩展了它们的宏,然后执行它们.但catch它不是一种功能或特殊形式,它只是try在前一步中寻找的东西.因此,当它正常执行时,您会得到与将其键入REPL时相同的错误.
你应该做的就是编写一个宏,你可以将整个代码扩展到你想要的try/ catch表达式.如果没有您想要完成的任何示例,很难给出具体的答案.
| 归档时间: |
|
| 查看次数: |
1128 次 |
| 最近记录: |