2017-12-09 1 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을 throw하므로 첫 번째 캐치가 발생하는 이유는 무엇입니까?

+0

왜 '로드 스트링'을 호기심으로 사용하고 있습니까? 이 매크로를 만든 경우 조금 더 간단하게 만들 수 있습니다. – 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이 예외가 발생되는 것을 인쇄 된 경우에만입니다 :

이 예외가 후 함수가 생성 될 때까지 호출되고 있지 않은 ( KeySeq.first 방법에서 발생되는 추적 스택의
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이 인쇄 순서를 실현하려고 할 때 해당 값을 반환했습니다.

0

입력 할 때 [1 2]은 Clojure MapEntry이 아닌 Clojure 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 블록을 사용하면 예외가 catch되지 않습니다.

관련 문제