2012-11-01 46 views
13

Tôi hơi bối rối bởi hàm clojure instance?. Có vẻ như rất vui khi có một cuộc tranh cãi duy nhất. Vì vậy,Ví dụ về clojure? đối số đơn

(instance? String) 

hoạt động tốt, nhưng luôn trả về false.

Tôi có thiếu gì đó ở đây không? Tôi đã làm điều này hai lần trong hai ngày, và cả hai lần tôi mất một thời gian khá dài để gỡ lỗi (vâng, tôi đồng ý, để làm cho sai lầm một lần có thể được coi là bất hạnh, nhưng hai lần trông giống như bất cẩn).

Tại sao nó không bị hỏng, với một lỗi cơ bản?

Lưu ý được thêm sau: Do Clojure 1.6, lỗi này đã được sửa!

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

+0

Bạn cũng có thể gọi phiên bản? với nhiều hơn 2 args: '(instance? String" a "0)' -> 'true' – Alex

+0

' (ví dụ?Chuỗi "a" 0) 'cho lỗi ArityException – amirteymuri

Trả lời

8

Thú vị ... mặc dù instance? được định nghĩa trong core.clj, dường như có xử lý đặc biệt được xây dựng trong để clojure.lang.Compiler cho (instance?) hình thức.

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))); 
      } 
     } 

Tôi giải thích rằng để có nghĩa là, khi bạn biên dịch/đánh giá một hình thức (instance?), chức năng quy định tại core.clj bị bỏ qua ủng hộ những hành vi khó có dây, mà không giải thích một thiếu đối số thứ hai là nil. Tôi đoán điều này được thực hiện vì lý do hiệu suất, như một loại lót.

Rõ ràng xử lý đặc biệt này chỉ áp dụng trong một số trường hợp nhất định (và tôi không quen thuộc với trình biên dịch để biết chúng là gì). Như minh họa bởi câu trả lời của Ankur, có nhiều cách gọi instance? gây ra hàm được xác định trong core.clj để được gọi.

+0

Đường dẫn nhanh trong trình biên dịch (phát ra biểu thức thể hiện) được thực hiện khi cuộc gọi là cuộc gọi trực tiếp với ký hiệu biểu thị trực tiếp một lớp. – Bendlas

+0

Có một vé cho điều đó ngay bây giờ: http://dev.clojure.org/jira/browse/CLJ-1171 – Bendlas

2

Nếu bạn nhìn vào instance? code bạn sẽ thấy rằng phương pháp isInstance của Class được gọi là:

(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)))) 

Hình như dưới mui xe, nil (or false) được coi là giá trị mặc định cho x tham số khi được chuyển đến số isInstance và trả về false.

+1

Điều này một mình không giải thích được hành vi được quan sát, bởi vì các hàm khác được định nghĩa theo cách này làm ném ngoại lệ của arity khi được gọi với số không chính xác của args. – Alex

+0

Bạn nói đúng. Tôi chưa thử nghiệm với phiên bản của riêng tôi về chức năng này. Lỗi của tôi. Và có vẻ như "vấn đề" này vẫn tồn tại kể từ khi Clojure 1.3: https://groups.google.com/forum/?fromgroups=#!topic/clojure-dev/OmmqMyd_uXE –

+0

Thú vị. Tôi đã tìm kiếm một vé được đề xuất bởi chủ đề này và không thể tìm thấy nó. Tôi đoán nó đã rơi xuống dưới dây. Tôi sẽ xem liệu tôi có thể tìm hiểu cách gửi báo cáo lỗi mới hay không. Thất bại này, tôi đoán tôi sẽ quấn dụ? cho bây giờ. –

3

Tôi nghĩ đó là lỗi. Nếu bạn xác định phiên bản mới của cá thể ?, ví dụ:

(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)))) 

bạn sẽ nhận được ngoại lệ dự kiến ​​

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

Hmm .... thú vị ... tất cả các cuộc gọi dưới đây thất bại (đó là cách nó được coi là):

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) 

Sự kiện tạo phiên bản mới của "phiên bản"? đối tượng chức năng hoạt động như nó là vụ phải làm việc:

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