Clojure: khuyết điểm (seq) so với liên hợp (danh sách)


98

Tôi biết rằng nó constrả về một seq và conjtrả về một tập hợp. Tôi cũng biết rằng conj"thêm" mục vào phần cuối tối ưu của bộ sưu tập, và consluôn "thêm" mục vào phía trước. Ví dụ này minh họa cả hai điểm sau:

user=> (conj [1 2 3] 4) ; returns a collection
[1 2 3 4]
user=> (cons 4 [1 2 3]) ; returns a seq
(4 1 2 3)

Đối với vectơ, bản đồ và tập hợp, những khác biệt này có ý nghĩa đối với tôi. Tuy nhiên, đối với danh sách chúng có vẻ giống hệt nhau.

user=> (conj (list 3 2 1) 4) ; returns a list
(4 3 2 1)
user=> (cons 4 (list 3 2 1)) ; returns a seq
(4 3 2 1)

Có bất kỳ ví dụ nào sử dụng danh sách trong đó conjso với consthể hiện các hành vi khác nhau hay chúng thực sự có thể hoán đổi cho nhau không? Được sắp xếp theo cách khác nhau, có ví dụ nào trong đó danh sách và seq không thể được sử dụng tương đương không?

Câu trả lời:


150

Một điểm khác biệt là conjchấp nhận bất kỳ số lượng đối số nào để chèn vào một bộ sưu tập, trong khi conschỉ lấy một:

(conj '(1 2 3) 4 5 6)
; => (6 5 4 1 2 3)

(cons 4 5 6 '(1 2 3))
; => IllegalArgumentException due to wrong arity

Một sự khác biệt khác là trong lớp của giá trị trả về:

(class (conj '(1 2 3) 4))
; => clojure.lang.PersistentList

(class (cons 4 '(1 2 3))
; => clojure.lang.Cons

Lưu ý rằng chúng không thực sự thay thế được cho nhau; đặc biệt, clojure.lang.Conskhông triển khai clojure.lang.Counted, vì vậy a counttrên nó không còn là một hoạt động thời gian cố định (trong trường hợp này, nó có thể giảm xuống 1 + 3 - 1 xuất phát từ chuyển tuyến tính qua phần tử đầu tiên, 3 đến từ (next (cons 4 '(1 2 3))là a PersistentListvà do đó Counted).

Ý định đằng sau những cái tên, tôi tin rằng, conscó nghĩa là khuyết điểm (truct a seq) 1 , trong khi conjcó nghĩa là liên kết (sắp xếp một mục vào một bộ sưu tập). Việc seqđược xây dựng bởi consbắt đầu với phần tử được truyền làm đối số đầu tiên của nó và có phần tử next/ restphần của nó là kết quả của việc áp dụng seqđối số thứ hai; như được hiển thị ở trên, toàn bộ điều là của lớp clojure.lang.Cons. Ngược lại, conjluôn trả về một tập hợp có cùng kiểu với tập hợp được chuyển đến nó. (Đại khái là vì a PersistentArrayMapsẽ được chuyển thành a PersistentHashMapngay khi nó phát triển vượt quá 9 mục nhập.)


1 Theo truyền thống, trong thế giới Lisp, conskhuyết điểm (tructs một cặp), vì vậy Clojure khác với truyền thống Lisp trong việc conshàm của nó tạo ra một seq không có truyền thống cdr. Việc sử dụng khái quát consnghĩa là "xây dựng một bản ghi của một số kiểu này hoặc kiểu khác để giữ một số giá trị cùng nhau" hiện đang phổ biến trong việc nghiên cứu các ngôn ngữ lập trình và triển khai chúng; đó là những gì có nghĩa là khi "tránh lợi dụng" được đề cập.


1
Thật là một bài viết tuyệt vời! Tôi đã không biết rằng có một loại khuyết điểm. Làm tốt!
Daniel Yankowsky

Cảm ơn. Vui khi biết điều đó. :-)
Michał Marczyk

2
Ngẫu nhiên, như một trường hợp đặc biệt, (cons foo nil)trả về một singleton PersistentList(và tương tự như vậy cho conj).
Michał Marczyk

1
Một lời giải thích tuyệt vời khác. Bạn thực sự là một jedi áo choàng!
dbyrne

1
Theo kinh nghiệm của tôi, coi danh sách là danh sách chứ không phải là seqs là điều quan trọng khi hiệu suất quan trọng.
cgrand

11

Tôi hiểu rằng những gì bạn nói là đúng: từ trong danh sách tương đương với khuyết điểm trong danh sách.

Bạn có thể nghĩ liên hợp là một hoạt động "chèn vào một nơi nào đó", và khuyết điểm là một hoạt động "chèn vào đầu". Trong một danh sách, hợp lý nhất là chèn ở đầu, vì vậy liên từ và khuyết điểm là tương đương trong trường hợp này.


8

Một sự khác biệt khác là bởi vì conjlấy một chuỗi làm đối số đầu tiên, nó hoạt động độc đáo với alterkhi cập nhật a refthành một số chuỗi:

(dosync (alter a-sequence-ref conj an-item))

Về cơ bản, điều này thực hiện (conj a-sequence-ref an-item)theo cách an toàn chủ đề. Điều này sẽ không hoạt động với cons. Xem chương về Đồng tiền trong Lập trình Clojure của Stu Halloway để biết thêm thông tin.


2

Một sự khác biệt là hành vi của danh sách?

(list? (conj () 1)) ;=> true
(list? (cons 1 ())) ; => false

4
khuyết điểm luôn trả về một chuỗi mà conj trả về cùng loại của một quy
Ning Sun

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.