2012-11-01 6 views
13

클로우 저에 의해 다소 혼란 스럽습니다 instance? 기능. 하나의 논쟁을하는 것은 상당히 행복해 보입니다. 따라서clojure 인스턴스? 하나의 인수

(instance? String) 

이 제대로 작동하지만 항상 false를 반환합니다.

여기에 뭔가가 있습니까? 저는 이틀에 걸쳐이 작업을 두 번했는데 두 번 모두 디버깅하는 데 오랜 시간이 걸렸습니다 (예, 한 번 실수로 여겨 질 수있는 실수는 있지만, 두 번은 부주의라고 생각합니다).

왜 아티스트 오류가 발생하지 않습니까?

나중에 추가 할 내용 : Clojure 1.6부터이 문제가 해결되었습니다! nil (or false)x 매개 변수의 기본값으로 간주,

(def 
    ^{:arglists '([^Class c x]) 
     :doc "Evaluates x and tests if it is an instance of the class 
      c. Returns true or false" 
     :added "1.0"} 
    instance? (fn instance? [^Class c x] (. c (isInstance x)))) 

는 후드처럼 보이는 : 당신이 instance? code 보면

http://dev.clojure.org/jira/browse/CLJ-1171

+0

인스턴스를 호출 할 수도 있습니다. 2 개 이상의 인수가있는 :'(인스턴스? 문자열 "a"0)'->'true' – Alex

+0

'(인스턴스?문자열 "a"0)'ArityException 오류가 발생합니다. – amirteymuri

답변

8

재미있는 ... 비록 (instance?) 형태의 clojure.lang.Compiler에 내장 된 특별한 처리가 나타납니다 :이 작동하도록되어 같은 함수 오브젝트 작동합니다.

Compiler.java, line 3498 :

if(fexpr instanceof VarExpr && ((VarExpr)fexpr).var.equals(INSTANCE)) 
     { 
     if(RT.second(form) instanceof Symbol) 
      { 
      Class c = HostExpr.maybeClass(RT.second(form),false); 
      if(c != null) 
       return new InstanceOfExpr(c, analyze(context, RT.third(form))); 
      } 
     } 

내가 그건 당신이 컴파일 할 때/(instance?) 양식을 평가하는 것을 의미하는 것으로 해석 core.clj에 정의 된 함수는없는 해석 않는, 하드 유선 행동에 찬성 무시 두 번째 인수는 nil입니다. 필자는 일종의 인라인 (in-lining)과 같은 성능상의 이유로이 작업이 완료되었다고 추측합니다.

분명히이 특수 처리는 특정 경우에만 적용됩니다 (그리고 나는 컴파일러가 무엇인지 알기에는 충분하지 않습니다). Ankur의 답변에서 알 수 있듯이 core.clj에 정의 된 함수가 호출되도록 instance?을 호출하는 방법이 있습니다.

+0

컴파일러의 빠른 경로 (instanceof 표현식을 내보내는)는 호출이 클래스를 직접 나타내는 기호가있는 직접 호출 인 경우에 사용됩니다. – Bendlas

+0

지금 티켓이 있습니다 : http://dev.clojure.org/jira/browse/CLJ-1171 – Bendlas

2

당신은 방법이 ClassisInstance가 호출되는 것을 볼 수 있습니다 isInstance에 전달되면 false을 반환합니다.

+1

이 방법으로 정의 된 다른 함수는 잘못된 수의 arg로 호출 될 때 arity 예외를 throw하기 때문에 관찰 된 동작을 설명하지 못합니다. – Alex

+0

당신 말이 맞아요. 나는이 함수의 내 자신의 버전으로 테스트하지 않았다. 내 잘못이야. Clojure 1.3 이후이 "문제"가 지속되는 것처럼 보입니다. https://groups.google.com/forum/?fromgroups=#!topic/clojure-dev/OmmqMyd_uXE –

+0

흥미 롭습니다. 이 스레드에서 제안한 티켓을 검색하여 찾을 수 없습니다. 나는 그것이 전선 아래에 추락했다고 생각한다. 새로운 버그 보고서를 제출하는 법을 배울 수 있는지 알게 될 것입니다. 이걸 실패하면 인스턴스를 랩핑 할 것 같아요? 지금 당장. –

3

나는 버그라고 생각합니다. 인스턴스의 새 버전을 정의한 경우?

(def 
^{:arglists '([^Class c x]) 
    :doc "Evaluates x and tests if it is an instance of the class 
     c. Returns true or false" 
    :added "1.0"} 
foo? (fn foo? [^Class c x] (. c (isInstance x)))) 

당신은 (있어야하는 방법입니다)

user=> (foo? String "bar") 
true 
user=> (foo? String 1) 
false 
user=> (foo? String) 
ArityException Wrong number of args (1) passed to: user$foo-QMARK- clojure.lang.AFn.throwArity (AFn.java:437) 
2

은 흠 .... 흥미있는 ... 모든 아래의 호출이 실패 예상되는 예외를 얻을 것이다 :

user=> (.invoke instance? String) 
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437) 

user=> (instance? (type "")) 
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437) 

user=> (apply instance? String []) 
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437) 

user=> (#'instance? Long) 
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437) 

"인스턴스"라는 새 인스턴스를 만드는 이벤트입니다. instance?core.clj에 정의되어

user=> (def a (.newInstance (aget (.getConstructors (type instance?)) 0) (into-array []))) 
#'user/a 
user=> (a String) 
ArityException Wrong number of args (1) passed to: core$instance-QMARK- clojure.lang.AFn.throwArity (AFn.java:437) 
user=> (a String "") 
true 
관련 문제