Clojure : cons (seq) 대 conj (list)


98

consseq를 conj반환하고 컬렉션 을 반환 한다는 것을 알고 있습니다. 또한 conj컬렉션의 최적 끝에 항목을 cons"추가" 하고 항상 항목을 맨 앞에 "추가" 한다는 것도 알고 있습니다. 이 예는 다음 두 가지 사항을 모두 보여줍니다.

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)

벡터,지도 및 세트의 경우 이러한 차이점이 이해가됩니다. 그러나 목록의 경우 동일하게 보입니다.

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)

여기서 목록을 사용하는 사례가 있습니까 conj대를 cons전시 다른 행동, 또는 그들이 진정으로 교환 할 수있다? 다르게 표현하면 목록과 시퀀스를 동등하게 사용할 수없는 예가 있습니까?

답변:


150

한 가지 차이점은 conj컬렉션에 삽입 할 인수를 원하는만큼 받아들이고 cons하나만 사용 한다는 것입니다.

(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

또 다른 차이점은 반환 값의 클래스입니다.

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

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

이들은 실제로 상호 교환 할 수 없습니다. 특히, clojure.lang.Cons구현하지 않습니다 clojure.lang.Counted소위, count그것에는 아마 1 + 3으로 줄일이 경우 일정 시간 동작 (더 이상 - 1은 3에서 온다, 첫 번째 요소를 통해 선형 탐색에서 비롯 (next (cons 4 '(1 2 3))PersistentList및 따라서 Counted).

이름 뒤에있는 의도는 conscons (truct a seq) 1을conj 의미하는 반면 conj (oin an item on a collection)을 의미합니다. 에 seq의해 생성되는 cons것은 첫 번째 인수로 전달 된 요소 로 시작 하고 두 번째 인수에 의 적용으로 인해 발생하는 것을 next/ rest부분 으로 갖습니다 seq. 위에 표시된 것처럼 모든 것은 클래스 clojure.lang.Cons입니다. 반대로, conj항상 전달 된 컬렉션과 거의 동일한 유형의 컬렉션을 반환합니다. (대략 9 개 이상의 항목 PersistentArrayMap이 늘어 나면 a 가 a PersistentHashMap로 바뀝니다.)


1 전통적으로 Lisp 세계에서 conscons (tructs a pair), 그래서 Clojure는 Lisp 전통에서 cons기능이 전통적 cdr. cons"여러 값을 함께 보유하기 위해 어떤 유형 또는 다른 유형의 레코드를 구성"을 의미 하는 일반화 된 용법 은 현재 프로그래밍 언어 및 그 구현 연구에서 유비쿼터스입니다. 그것이 "consing consing"이 언급 될 때의 의미입니다.


1
정말 멋진 글입니다! 나는 단점 유형이 있다는 것을 알지 못했습니다. 잘 했어!
Daniel Yankowsky 2010 년

감사. 그 말을 듣고 기쁩니다. :-)
Michał Marczyk 2010-06-09

2
덧붙여서, 특별한 경우 (cons foo nil)로 싱글 톤 PersistentList(그리고 마찬가지로)을 반환합니다 conj.
Michał Marczyk 2010 년

1
또 다른 훌륭한 설명. 당신은 정말 클로저 제다이입니다!
dbyrne 2010 년

1
내 경험상, 목록을 목록으로 취급하는 것은 성능이 중요 할 때 중요합니다.
cgrand

11

내 이해는 당신이 말하는 것이 사실이라는 것입니다. 목록의 conj는 목록의 cons와 동일합니다.

conj는 "어딘가에 삽입"작업으로 생각할 수 있고, 단점은 "머리에 삽입"작업으로 생각할 수 있습니다. 목록에서 헤드에 삽입하는 것이 가장 논리적이므로이 경우 conj와 cons는 동일합니다.


8

또 다른 차이점은 conj시퀀스를 첫 번째 인수로 사용 하기 때문에 altera ref를 일부 시퀀스로 업데이트 할 때 잘 작동한다는 것입니다 .

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

이것은 기본적으로 (conj a-sequence-ref an-item)스레드로부터 안전한 방식으로 수행됩니다. 이것은 cons. 자세한 내용은 Stu Halloway의 Programming Clojure의 동시성에 대한 장을 참조하십시오 .


2

또 다른 차이점은 목록의 동작입니까?

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

4
cons는 항상 conj가 제공된 것과 동일한 유형을 반환하는 시퀀스를 반환합니다.
Ning Sun

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.