Clojure에서 목록 위에 벡터를 사용해야하는 경우와 다른 방법은 무엇입니까?


답변:


112

다시 한 번, 나는 참을성이 없어서 Freenode의 #clojure에 질문하여 내 자신의 질문에 대답 한 것 같습니다. Stackoverflow.com에서 자신의 질문에 대답하는 것이 좋습니다. : D

나는 Rich Hickey와 빠른 토론을했으며 여기에 요점이 있습니다.

[12:21] <Raynes>    Vectors aren't seqs, right?
[12:21] <rhickey>   Raynes: no, but they are sequential
[12:21] <rhickey>   ,(sequential? [1 2 3])
[12:21] <clojurebot>    true
[12:22] <Raynes>    When would you want to use a list over a vector?
[12:22] <rhickey>   when generating code, when generating back-to-front
[12:23] <rhickey>   not too often in Clojure

프리 노드를 사용하는 동안 어두운 곳으로 와서 #stackoverflow에 가입하십시오! :-P
Chris Jester-Young

나는 실제로 유휴 상태였습니다. IRC 클라이언트를 전환했는데 내 autojoin 목록에 #stackoverflow를 추가하려고 생각하지 않았습니다.
Rayne

나는 Lisp 초보자이지만 모든 코드가 데이터와 상호 교환 가능하다는 아이디어를 벡터, 맵 및 세트가 깨뜨릴 수 있을지 궁금했습니다. 아니면 Clojure를 실용적인 Lisp로 만드는 것 중 하나입니까? (또는 벡터를 평가할 수 있습니까?)
Rob Grant

23
이것은 완전히 도움이되지 않는 채팅 스 니펫입니다. "코드 생성" "뒤에서 앞으로 생성"-> 정확히 의미합니까 ?? 내 책에서 게으름 + 선언적 스타일 = 훨씬 더 나은 성능을 제공하지만 Clojure의 모든 곳에서 벡터가 제안되어 완전히 혼란 스럽기 때문에이 질문에 어려움을 겪고 있습니다.
Jimmy Hoffa

22
@JimmyHoffa 내가 이해하는 방법 : "코드 생성"= "매크로 내부"(대부분의 코드는 함수 호출이므로 목록이므로); "다시 앞뒤로 생성"= "앞에 순서대로 작성".
omiel

87

Java 프로그래밍을 많이 해왔고 Java 콜렉션 프레임 워크에 익숙한 경우와 같은 목록 LinkedList과 벡터를 생각하십시오 ArrayList. 따라서 컨테이너를 거의 같은 방식으로 선택할 수 있습니다.

더 명확하게 설명하려면 시퀀스의 앞이나 뒤에 개별 항목을 많이 추가하려는 경우 매번 항목을 뒤섞을 필요가 없으므로 연결된 목록이 벡터보다 훨씬 좋습니다. 그러나 특정 요소 (목록의 앞이나 근처가 아닌)에 자주 액세스하려면 (예 : 임의 액세스) 벡터를 사용하는 것이 좋습니다.

그런데 벡터를 쉽게 seq로 바꿀 수 있습니다.

user=> (def v (vector 1 2 3))
#'user/v
user=> v
[1 2 3]
user=> (seq v)
(1 2 3)
user=> (rseq v)
(3 2 1)

벡터는 seq가 아니지만 순차적입니다. (source : freenode의 #clojure에 대한 자신도 풍부합니다.) 또한 Java를 전혀 모르지만 Rich는 단지 내 질문에 대답했습니다.
Rayne

1
내 게시물을 편집 하여 seq 함수를 통해 벡터를 seq 로 만들 수 있습니다 . :-)
Chris Jester-Young

2
실제로 질문에 대한 답변이 되었기 때문에 답을 선택하십시오. 본인은 본인의 답변을 올바른 것으로 선택하는 것을 정말로 좋아하지 않습니다. 옳지 않은 것 같습니다. 감사. :)
Rayne

deque는 first와 last를 추가 할 경우 연결된리스트보다 낫습니다. LLs는 꽤 끔찍하다 : P
박스

1
@boxed 벡터 위에 또는 ArrayList효과적으로 ArrayDeque자신을 다시 구현하지 않고 deque를 구현할 수 없습니다 .
Chris Jester-Young

43

벡터는 랜덤 액세스 시간이 O (1)이지만 사전 할당되어야합니다. 목록은 동적으로 확장 될 수 있지만 임의의 요소에 액세스하는 것은 O (n)입니다.


3
기술적으로, 링크 된 목록에는 O (1) 액세스 시간이 있습니다 ... 앞면 또는 뒷면 요소에만 액세스하는 경우. :-P 그러나 벡터는 O (1) 랜덤 액세스를 갖습니다. :-)
Chris Jester-Young

4
(위에 설명 된 "연결된 목록"은 이중 연결 목록을 나타냅니다. 단일 연결 목록은 앞면 요소에만 O (1) 액세스 할 수 있습니다. :-P)
Chris Jester-Young

1
누군가 Clojure에 뛰어 들었을 때, 이것은 더 많은 투표로 다른 두 사람보다 더 나은 답변입니다. 다른 두 사람은 아무 소용이 없습니다.
keithjgrant

이 백 요소에 대한 참조를 저장하는 경우 @ ChrisJester - 젊은 싱글 링크 목록은 뒤쪽 O (1) 접근을 지원할 수있는 그런 .
길 베이츠

30

벡터를 사용하는 경우 :

  • 인덱싱 된 액세스 성능-인덱싱 된 액세스에 대한 ~ O (1) 비용 vs. 목록에 대한 O (n)
  • 추가-conj 포함 ~ O (1)
  • 편리한 표기법-어느 쪽이든 작동하는 상황에서 리터럴 목록에 대해 '(1 2 3)보다 타이핑하고 읽는 것이 더 쉽다는 것을 알았습니다.

목록을 사용하는 경우 :

  • 시퀀스로 액세스하려는 경우 (목록은 새 객체를 할당하지 않고 seq를 직접 지원하므로)
  • 앞에-cons 또는 conj가있는 목록의 시작 부분에 추가하는 것은 O (1)입니다.

3
양쪽 끝에 추가 / 제거 할 때에도 목록은 매우 끔찍한 선택입니다. CPU와 특히 메모리에서 deque가 훨씬 좋습니다. 시도의 github.com/pjstadig/deque-clojure
박스

2
다시 :은 ~O(1), 사람들을 위해 누구에게이 비용의 설명이 도움이 될 수 있습니다 - stackoverflow.com/questions/200384/constant-amortized-time
Merlyn 모건 - 그레이엄

13

간단한 참고 사항 :

"Vectors는 seqs가 아니지만 Lists는 읽습니다." 

시퀀스는 목록 또는 벡터 (또는 맵 또는 세트)보다 일반적입니다.
불행히도 REPL은 목록과 시퀀스를 동일하게 인쇄 한다는 것이 불행합니다 . 왜냐하면 목록이 다르더라도 실제로는 목록처럼 보이기 때문입니다. (seq) 함수는 목록을 포함하여 많은 다른 것들로부터 시퀀스를 만들고, seq를 사용하여 멋진 일을하는 수많은 함수 중 하나에 seq를 공급할 수 있습니다.

user> (class (list 1 2 3))
clojure.lang.PersistentList

user> (class (seq (list 1 2 3)))
clojure.lang.PersistentList

user> (class (seq [1 2 3]))
clojure.lang.PersistentVector$ChunkedSeq

Sec에는 이미 seq 인 경우 인수를 반환하는 바로 가기가 있습니다.

user> (let [alist (list 1 2 3)] (identical? alist (seq alist)))
true
user> (identical? (list 1 2 3) (seq (list 1 2 3)))
false

static public ISeq seq(Object coll){
        if(coll instanceof ASeq)
                return (ASeq) coll;
        else if(coll instanceof LazySeq)
                return ((LazySeq) coll).seq();
        else
                return seqFrom(coll);
}

리스트는 시퀀스이지만 다른 것들도 있지만 모든 시퀀스가리스트 인 것은 아닙니다.


나는 작은 점을 선택하는 것을 의미하지 않으며, 유용한 것을 지적 할 수있는 기회입니다. 많은 사람들이 이미 이것을 알고 있습니다 :)
Arthur Ulfeldt

2
당신은 class대신에 의미 하지 class?않습니까?
qerub

clojure 업데이트 후 예제가 변경되었는지 확실하지 않지만 (1.5에 있다고 생각합니다) 두 예제가 모두 반환됩니다. clojure.lang.PersistentList 나에게 . 나는 당신이 쓰는 의미 있으리라 믿고있어 class없습니다 class?.
Adrian Mouat

나는 정말로했다! 나는 그것을 고칠 것이다
Arthur Ulfeldt

아직도 혼란 스러웠다. 이후 class반환 당신이 언급 한 이러한 식의 모두 동일 PersistentList,이 순서와 목록이 실제로 똑같은 것을 의미?
johnbakers
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.