Clojure 为什么这个异常没有被捕获?
如果我定义以下函数Clojure 为什么这个异常没有被捕获?,clojure,Clojure,如果我定义以下函数 (defn catcher [x] (try (load-string x) (catch Exception e (prn "caught"))) ) (catcher“(+2\'2\”)=>“捕获” 但是,(catcher)(键[12])”=>ClassCastException java.lang.Long不能转换为java.util.Map$Entry 通常这两个输入都会抛出ClassCastException,那么为什么只捕获第
(defn catcher [x] (try
(load-string x)
(catch Exception e
(prn "caught"))) )
(catcher“(+2\'2\”)
=>“捕获”
但是,(catcher)(键[12])”
=>ClassCastException java.lang.Long不能转换为java.util.Map$Entry
通常这两个输入都会抛出ClassCastException,那么为什么只捕获第一个呢?在尝试打印
(键[1 2])的结果时,似乎发生了异常。
在这里,您可以看到表达式实际上正在创建/返回一个KeySeq
,而没有抛出/捕获异常。只有当打印了KeySeq
时,才会引发异常:
java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.Map$Entry
at clojure.lang.APersistentMap$KeySeq.first(APersistentMap.java:168)
at clojure.lang.RT.first(RT.java:685)
at clojure.core$first__5107.invokeStatic(core.clj:55)
at clojure.core$print_sequential.invokeStatic(core_print.clj:64)
at clojure.core$fn__7021.invokeStatic(core_print.clj:174)
at clojure.core$fn__7021.invoke(core_print.clj:174)
at clojure.lang.MultiFn.invoke(MultiFn.java:233)
at clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__784.send(pr_values.clj:35)
请注意,在堆栈跟踪中,当REPL尝试实现打印序列时,此异常源自
KeySeq.first
方法(在函数创建并返回其值后才会调用该方法)。请注意,[1 2]
,当您键入它时,它是一个clojure向量,不是ClojureMapEntry
。请参见以下结果:
(ns tst.demo.core
(:use tupelo.test)
(:require
[tupelo.core :as t] ) )
(t/refer-tupelo)
(dotest
(newline)
(let [my-map {:a 1 :b 2}
map-entries (vec my-map)
map-entry-1 (first map-entries)
map-keys (keys my-map)
entry-1-key (key map-entry-1)
]
(is= map-entries [[:a 1] [:b 2]] )
(is= map-entry-1 [:a 1] )
(is= map-keys [:a :b])
(is= entry-1-key :a)
(spyxx my-map)
(spyxx map-entries)
(spyxx map-entry-1)
(spyxx map-keys)
(spyxx entry-1-key)
))
结果如下:
Testing tst.demo.core
my-map => <#clojure.lang.PersistentArrayMap {:a 1, :b 2}>
map-entries => <#clojure.lang.PersistentVector [[:a 1] [:b 2]]>
map-entry-1 => <#clojure.lang.MapEntry [:a 1]>
map-keys => <#clojure.lang.APersistentMap$KeySeq (:a :b)>
entry-1-key => <#clojure.lang.Keyword :a>
Ran 2 tests containing 4 assertions.
0 failures, 0 errors.
然而,它们是不同的类型。当您执行(加载字符串“[1 2]”
时,它返回的是向量,而不是映射,因此您无法调用键
函数
第二部分
在你最初的问题中,你问了
(catcher "(keys [1 2])") => Exception
我怀疑load string
正在返回一个延迟结果,这在您的代码退出try catch块之前是无法实现的,这就是为什么无法捕获异常。出于好奇,您为什么还要使用load string
?看起来如果你把它做成一个宏,你就可以把它简化一点。我想要一个try/catch的测试平台,但我还不习惯使用宏。你仍然会使用try/catch。它看起来像是(defmacro catcher[body]`(try~@body catch Exception e(prn“catch”))
(显然,您可以用双反勾号包围代码,以在注释中转义单反勾号)。@Carcigenicate+1表示双反勾号trick@madstap哎,,我很高兴在我的编辑期结束之前就发现了这个问题。我本来打算在Meta上做一个自我问答,但是已经有一篇文章描述了它。
`[1 2]`
(catcher "(keys [1 2])") => Exception