2012-02-01 42 views
10

Cách tốt nhất để phát hiện xem một đối tượng có phải là một mảng nguyên thủy Java trong Clojure không?Kiểm tra xem một đối tượng có phải là một mảng nguyên thủy Java trong Clojure

Lý do tôi cần điều này là để làm một số xử lý đặc biệt đối với mảng nguyên thủy, mà có thể giống như thế:

(if (byte-array? object) 
    (handle-byte-array object)) 

Đó là trong một mảnh khá hiệu suất nhạy cảm của mã vì vậy tôi muốn tránh phản ánh nếu có thể.

+1

Không chắc chắn mã Clojure sẽ là gì, nhưng bạn có thể tạo một mảng trống cho mọi kiểu nguyên thủy, gọi getClass() trên các giá trị đó và lưu vào bộ nhớ cache kết quả. Đối tượng Class nên giống nhau đối với mọi mảng của kiểu nguyên thủy đó - bạn sẽ so sánh các đối tượng được lưu trữ với 'object.getClass()'.(getClass() không thực sự là một cuộc gọi chậm) – millimoose

Trả lời

8

bạn có thể sử dụng phản ánh một lần để có được lớp từ tên gọi, bộ nhớ cache này và sau đó so sánh phần còn lại cho rằng

(def array-of-ints-type (Class/forName "[I")) 
(def array-of-bytes-type (Class/forName "[B")) 
... 

(= (type (into-array Integer/TYPE [1 3 4])) array-of-ints-type) 
true 
+0

Tốt, giống như ý tưởng lưu bộ nhớ đệm các lớp mảng nguyên thủy. Mặc dù nó tấn công tôi như một chút rằng những điều này chưa được định nghĩa ở đâu đó trong Java! – mikera

+0

và những người đã đưa ra tên "[tôi" tại đó ... –

+3

'" [J "' cho 'long' s thậm chí còn đáng yêu hơn, phải không? Ngoài ra, bất cứ ai đã đưa ra các dấu ngoặc mở chưa từng có trong các giá trị trả về '.toString', bất cứ khi nào tôi tìm hiểu tên của họ, dấu mũ của tôi sẽ sẵn sàng. Nó phá vỡ paredit cho tôi tất cả các thời gian, chưa kể [hiệu ứng trên tâm lý của tôi] (http://xkcd.com/859/). (Thay thế 'phương thức in 'cho tất cả các trường hợp liên quan có thể hoặc không khả thi - cảm giác ruột hiện tại của tôi là * không *.) –

7
(defn primitive-array? [o] 
    (let [c (class o)] 
    (and (.isArray c) 
     (.. c getComponentType isPrimitive)))) 

Đối với trường hợp cụ thể, bạn có thể sử dụng giống như sau:

(defn long-array? [o] 
    (let [c (class o)] 
    (and (.isArray c) 
     (identical? (.getComponentType c) Long/TYPE)))) 
+0

Tất cả các bí mật được đặt trần: http://docs.oracle.com/javase/6 /docs/api/java/lang/Class.html – Bill

4

Hoặc đơn giản cũ instance?:

(instance? (RT/classForName "[B") thing) 
+0

Bạn đang sử dụng bí danh nào cho 'RT'? Bạn có nghĩa là '(Class/forName" [B ")' phải không? –

+0

@DavidJames RT là clojure.lang.RT. – kotarak

4

Như đã chỉ bởi Arthur Ulfeldt, bạn có thể sử dụng Class/forName, ví dụ, như ở đây:

(def byte_array_class (Class/forName "[B")) 

(defn byte-array? [arr] (instance? byte_array_class arr)) 

Nếu bạn muốn tránh dây ma thuật như "[B" khi bộ nhớ đệm các lớp học, bạn có thể áp dụng class để một mảng hiện đối tượng:

(def byte_array_class (class (byte-array []))) 
+1

Thậm chí đơn giản hơn: '(def byte-array-class (lớp (byte-mảng 0)))'. (Không gạch dưới!) –

5

để kiểm tra cho một mảng byte mà không cần dùng phản ánh bạn có thể làm điều này:

(def ^:const byte-array-type (type (byte-array 0))) 
(defn bytes? [x] (= (type x) byte-array-type)) 

Không chắc chắn lý do tại sao, nhưng bạn thậm chí có thể xếp loại byte-mảng với ^:const.

2

Đạo cụ cho tất cả các câu trả lời khác. Ở đây nó là như một lớp lót:

(def byte-array? (partial instance? (Class/forName "[B"))) 

Đối với nguyên thủy khác, hãy tham khảo http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getName%28%29 (hoặc spec java). Hoặc chỉ cần làm những gì Gerrit gợi ý với (type (xyz-array 0)). Cụ thể, bạn có thể sử dụng:

"[Z" boolean array 
"[B" byte array 
"[C" char array 
"[D" double array 
"[F" float array 
"[I" integer array 
"[J" long array 
"[S" short array 

Kể từ khi thực hiện đã được đề cập, đây là một chuẩn mực kết quả nhỏ chạy (time (dotimes [_ 500000] (byte-array? x))), và với byte-array-class def'd

(def byte-array? (partial instance? (Class/forName "[B"))) 
78.518335 msecs 
(defn byte-array? [obj] (instance? byte-array-class obj)) 
34.879537 msecs 
(defn byte-array? [obj] (= (type obj) byte-array-class)) 
49.68781 msecs 

instance? vs type = dụ? thắng

partial vs defn = defn thắng

nhưng bất kỳ các phương pháp tiếp cận có thể sẽ không phải là một nút cổ chai trong hoạt động.

Các vấn đề liên quan