clojure - 如何在 Clojure 中捕获一个 arity 异常?
问题描述
我正在尝试像这样捕获一个arity异常:
(try
(inc)
(catch clojure.lang.ArityException e
(str "caught exception: " (.getMessage e))))))
在这种情况下,我在inc
没有传递一个数字的情况下调用它,它正确地抛出了一个异常。但是,当我运行它时不会捕获该异常:
(try
(inc)
(catch clojure.lang.ArityException e
(str "caught exception: " (.getMessage e))))))
; => CompilerException clojure.lang.ArityException: Wrong number of args (0) passed to: core/inc--inliner--4489
试图抓住任何Exception
一般而不是clojure.lang.ArityException
仍然抛出它。
我相信任何在 Clojure 开发方面经验丰富的人都会立即发现我的错误。
解决方案
ArityException
在某些情况下你可以 catch ;取决于上下文和导致ArityException
.
我要马上承认我正在推测某些方面,因为我以前从未对此进行过深入的探索。
首先,看看如果你inc
在很明显提供的参数数量错误的上下文中调用会发生什么:
(inc)
CompilerException clojure.lang.ArityException: Wrong number of args (0) passed to: core/inc--inliner--4489, compiling: . . .
有趣的部分是inc--inliner--4489
。如果您查看 的定义inc
,它会附加以下元数据:
:inline (fn [x] `(. clojure.lang.Numbers (~(if *unchecked-math* 'unchecked_inc 'inc) ~x)))
我以前从未:inline
深入研究过,但我一直认为这意味着它将尝试内联调用以(略微)减少开销。在这种情况下,它试图内联inc
只是对clojure.lang.Numbers/inc
, 或clojure.lang.Numbers/unchecked_inc
;的调用 取决于 的状态*unchecked-math*
。还要注意错误是如何开始的:
CompilerException clojure.lang.ArityException
在您的示例中,您无法直接捕获,(inc)
因为该调用在编译时甚至在代码运行之前就失败了。它知道这(inc)
永远不会正确,所以它立即失败。不过,这是一件好事。(inc)
永远不会是正确的,所以无论如何试图抓住它是没有意义的。
然而,在某些情况下,捕获一个 arity 异常可能是有意义的(尽管可能有更好的方法来解决这个问题*
)。假设您不允许调用 toinc
被内联,正如@Rulle 建议apply
的那样,使用参数:
(try
(apply inc [])
(catch clojure.lang.ArityException e
(println "Caught!")))
Caught!
编译器无法确定是否inc
会失败,因为它取决于提供给apply
;的参数数量。这可能取决于运行时的事情。在这种情况下,代码实际上是可以运行的,也可以ArityException
被捕获。
从:inline
等式中取出,您还可以看到您的自定义函数可以更轻松地ArityException
捕获它,因为调用不是内联的,因此它不会在编译时失败:
(defn hello [arg])
(try
(hello) ; No apply
(catch clojure.lang.ArityException e
(println "Caught!")))
Caught!
*
我不能说我曾经必须赶上ArityException
,而且我想不出在任何情况下这样做是合适的。即使您正在使用apply
,提前验证论点会更有意义,甚至重新考虑使用apply
. 如果 usingapply
导致ArityException
,您的逻辑可能在某个地方存在缺陷,而 usetry
只是在使用创可贴。
推荐阅读
- reactjs - 输入控件在 react-bootstrap 的 Multi Modal 上不可编辑
- node.js - 在 nodeOpcua 中写入数组
- android - 是否还需要调用 GoogleApiClient connect() 和 disconnect()?
- airflow - Airflow v1.10.3 是否默认附带 Flask App builder (FAB) 并且需要在 webserver_config.py 中进行 Google Oauth 配置?
- roku - 是否可以在 ROKU 中从一个文件到另一个文件的场景访问?
- django - 在 Django Rest Framework 中根据 ID 检索 API 中的数据
- javascript - 为什么firebase会返回一个pomise?
- python - 更改配置后收到意外的日志消息
- ios - HighCharts iOS Wrapper:向下钻取事件被触发,但属性为零
- sql-server - 如何在 Excel 中将 SSAS Dimension 属性数据类型设为数字