2011-09-15 1010 views
10

Clojure:Không thống nhất với trình tự của Clojure?

1:13 user=> (first (conj '(1 2 3) 4)) 
4 
1:14 user=> (first (conj [1 2 3] 4)) 
1 
; . . . 
1:17 user=> (first (conj (seq [1 2 3]) 4)) 
4 

tôi hiểu những gì đang xảy ra, nhưng nên làm việc này khác nhau?

+0

Tôi đã học Clojure kể từ tháng 5 năm nay. Tôi thấy việc đào sâu vào các bài tập như thế này rất hữu ích, nhất là khi tôi chưa bao giờ học một ngôn ngữ giống Lisp trước Clojure. – octopusgrabbus

Trả lời

20

Tài liệu cho conj (từ clojure.org):

conj [oin]. Trả lại bộ sưu tập mới với xs 'đã thêm'. (conjil item) trả về (item). 'Ngoài ra' có thể xảy ra ở các 'địa điểm' khác nhau tùy thuộc vào loại bê tông.

Sẽ hiệu quả hơn khi "thêm" phần tử vào cuối vectơ, trong khi hiệu quả hơn để làm như vậy ở đầu danh sách. conj sử dụng bất cứ điều gì là hiệu quả nhất cho cấu trúc dữ liệu bạn cung cấp cho nó.

Trong ví dụ bạn đưa ra, '(1 2 3)(seq [1 2 3]) cả thực hiện ISeq (xem documentation for seq?), trong khi [1 2 3] không.

Clojure conj cuối cùng gọi phương thức cons (không bị nhầm lẫn với hàm cons - phương pháp này là mã clojure nội bộ) trên cấu trúc dữ liệu cơ bản; đối với các vectơ (PersistentVector), cons thêm các phần tử vào cuối, trong khi các danh sách được thêm vào phía trước (phương thức cons cho PersistentList s trả về một danh sách mới với phần tử mới làm đầu của nó và danh sách hiện tại làm đuôi của nó) .

+0

Đoạn cuối cùng tôi nghĩ là không chính xác (ít nhất trong Clojure 1.2.1): '(cons 4 [1 2 3])', ví dụ, không chắp thêm phần tử nhưng thêm vào nó, dẫn đến '(4 1 2 3) '. Phần còn lại của câu trả lời, mặc dù, là hoàn toàn chính xác. –

+0

Bạn đúng, Zach, nhưng chức năng 'cons' của Clojure (được thực hiện trong' Clojure.lang.RT/cons') khác với các phương thức 'cons' được thực thi trong' PersistentVector', 'PersistentList' và cetera. – Gert

+0

Ah, bây giờ tôi hiểu bạn. Cách nó được diễn đạt, có vẻ như bạn đang đề cập đến chức năng cốt lõi 'cons'. –

6

Nếu bạn nhìn vào Clojure Data Structures

bạn sẽ thấy conj mà làm việc khác với danh sách và vectơ.

conj đặt mục được thêm vào ở phía trước danh sách và ở cuối vectơ.

Tôi cũng đề nghị xem xét Clojure API conj

trong đó có một số ví dụ tốt đẹp. ClojureDocs tổng thể có một số ví dụ rất hay cho hầu hết các lệnh Clojure.