如果我定义以下功能
(defn catcher [x] (try
(load-string x)
(catch Exception e
(prn "caught"))) )
(catcher "(+ 2 \"2\")")
=> "抓"
但是(catcher "(keys [1 2])")
=> ClassCastException java.lang.Long无法强制转换为java.util.Map $ Entry
通常这两个输入都抛出ClassCastException,那么为什么只有第一个被捕获?
答案 0 :(得分:1)
在尝试打印 (keys [1 2])
的结果时,似乎发生了异常。
(type (catcher "(keys [1 2])"))
=> clojure.lang.APersistentMap$KeySeq
在这里你可以看到表达式实际上是创建/返回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)
请注意,在堆栈跟踪中,此异常源自KeySeq.first
方法(在 实现打印顺序。
答案 1 :(得分:0)
请注意[1 2]
,当您输入时,{* 1}}是一个clojure vector
字面值,而不是Clojure MapEntry
。看到这些结果:
(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.
问题是MapEntry
打印与矢量相同:
`[1 2]`
但是,它们是不同的类型。执行(load-string "[1 2]")
时,它会返回向量,而不是地图,因此您无法调用keys
函数。
在您的原始问题中,您询问
(catcher "(keys [1 2])") => Exception
我怀疑load-string
正在返回一个惰性结果,直到你的代码退出try-catch块之后才能实现,这就是没有捕获异常的原因。