2017-12-09 12 views
1

私は次の関数を定義する場合この例外がキャッチされないのはなぜですか?

(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 $エントリにキャストすることはできません

通常、これらの入力は両方ともClassCastExceptionをスローします。なぜ、最初のものだけがキャッチされるのですか?

+0

なぜあなたは好奇心から 'load-string'を使用していますか?これをマクロにすると、少し単純化することができるようです。 – Carcigenicate

+0

私はtry/catchのためのテストベッドを望んでいましたが、私はまだマクロに慣れていません。 – planarian

+2

あなたはtry/catchを使います。これは ''(defmacro catcher [body] '(try〜@ body catch Exception e(prn" caught ")))' 'のように見えます(コメント内で単一のバッククイックをエスケープするために、 – Carcigenicate

答えて

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方法(から発信されるトレースし、 REPLが印刷のシーケンスを実現しようとすると、その値が返されました)。

0

[1 2]は、入力すると、Clojure MapEntryではなく、クロージャーvectorリテラルであることに注意してください。これらの結果を参照してください。結果と

(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関数を呼び出すことはできません。あなたの元の質問に


パート#2

、あなたはおよそ

(catcher "(keys [1 2])") => Exception 

を尋ねる私はload-stringは怠惰な結果を返して、そしてこれはあなたのコードが出た後まで実現されていないと思われますtry-catchブロックであり、例外がキャッチされないのはこのためです。

関連する問題