clojure에서 list와 vector의 차이점은?

2013-09-30 09:40

최근에 functional programming에 관심을 가지면서 프로그래밍 클로저 : Lisp(http://www.yes24.com/24/Goods/3907543)) 책을 보고 있다. JVM 기반 언어 중에 Scala도 있지만 완전히 새로운 형태의 언어를 공부해 보고 싶은 마음에 클로저를 보고 있다. 아직 생소한 것이 많은데 언젠가는 익숙해 질거라 생각하면서 보고 있다.

책을 읽다보니 궁금한 점이 있어 글을 남긴다. clojure의 자료 구조를 보면 list와 vector를 제공하고 있다. API를 사용하는 입장에서 보면 둘 사이의 차이점이 잘 드러나지 않는다. 자바 개발자의 경우 vector를 JDK API의 Vector로 이해할 수도 있다. 사용 관점에서 보면 똑같다.

국내에 clojure를 사용하는 개발자가 많지 않을 것으로 생각하는데 list와 vector의 차이점에 대해 이야기해 보고 싶어 글을 남긴다.

구글에 검색해 보면 다음과 같은 글을 볼 수 있다. * http://stackoverflow.com/questions/11504236/as-a-data-container-what-are-the-main-differences-between-vector-and-list * http://stackoverflow.com/questions/1147975/in-clojure-when-should-i-use-a-vector-over-a-list-and-the-other-way-around

list는 자바의 LinkedList와 같은 용도이고, vector는 자바의 ArrayList와 같다고 이해하면 된다는 이야기도 보인다. clojure는 왜 이 두 가지 자료 구조를 분리해서 제공하고 있을까? 어떤 경우에 list를 사용하고 어느 경우에 vector를 사용해야 할까?

4개의 의견 from FB

5개의 의견 from SLiPP

2013-09-30 12:46

Clojure의 list는 전통적인 리스프 언어들에서 사용하는 리스트입니다. Cons Cell들을 연결해서 만듭니다. http://en.wikipedia.org/wiki/Cons#Lists 여기 보세요. 단일 연결 리스트이고 요소 추가와 제거를 한 쪽 방향에서만 하기 때문에 여러가지 특징이 있습니다. 대표적으로 리스트에 요소를 추가하거나 제거해도 변경하기 전의 리스트도 그대로 유지되는 장점이 있습니다. http://en.wikipedia.org/wiki/Persistent_data_structure 라고 하죠.

반면 단점들도 있습니다. 대표적으로 꼬리쪽에 가까운 요소를 접근하기 어렵습니다. Clojure의 vector는 list의 장점을 유지하면서 단점을 줄이려고 고안하지 않았을까 생각합니다. Persistent data structure이면서도 거의 O(1)으로 빠릅니다. 2칸 짜리 셀 대신에 32칸짜리 셀을 쓰고 트리로 구성하여 단점을 극복한 것 같네요.

list는 왜 남겨뒀을까... 음... 아무래도 순차적으로 접근하거나 머리쪽의 접근이 많을 경우에는 여전히 list가 vector다 좋은 특징을 보이니까 남겨뒀을 것 같네요.

2013-09-30 14:13

@eungju.park.1 위 링크에 있듯이 그냥 ArrayList와 LinkedList의 차이 정도로 이해하려고 했는데 이 둘과는 다른 부분도 많네. 자료구조는 보면 볼 수록 재미있는 듯하다.

근데 잘 모르는 부분이 있어서 다시 질문..

Cons Cell이라는 것은 Clojure의 cons가 그렇듯이 list 제일 앞에 element를 추가하는 방식으로 element를 관리한다는 의미로 받아들이면 되는 건가? 이 때 두개의 Cell을 사용한다는 것은 기존 list를 가지는 cell과 새로 추가되는 element를 하나의 cell로 보면 되는 건가?

답변에서 이야기한 cell 용어가 무엇을 의미하는지 명확하지 않다 보니까 딱 피부로 와닿지 않는 부분이 있네. Cell에 대해서 좀 더 구체적으로 설명해 줄 수 있을까?

2013-09-30 22:56

@자바지기 요소를 가리키는 공간과 기존 리스트를 가리키는 공간을 합쳐서 cons-cell이라고 합니다. 리스프에서 첫 번째 공간을 car이라고 하고 두 번째 공간을 cdr이라고 하고 함수로도 사용합니다. (car '(1 2)) => 1 이고 (cdr '(1 2)) => (2) 입니다. Clojure는 car, cdr이 없고 대신 first, next가 있습니다. 리스프의 list로 설명을 했는데 실제로는 리스프 list와 클로저 list가 좀 다릅니다. 더 정확하게 알고 싶으시면 The Joy of Clojure의 Chapter 5 Composite data types를 읽어보시는게 제일 좋겠네요. 아니면 코드를...

Clojure에서는 list보다 vector를 선호하는 것 같네요. list는 주로 코드를 표현할 때 쓴다고 합니다.

2013-10-01 09:16

clojure의 vector 내부와 clojure의 persistent 개념을 그림을 통해 정말 잘 설명하고 있는 문서라 공유한다.

http://hypirion.com/musings/understanding-persistent-vector-pt-1

이 문서를 보면 vector와 persistent 개념이라는 두 마리 토끼를 잡을 수 있지 않을까? 아래 페북 글에서 정재훈 씨가 쓴 vector는 index 방식으로 구현되어 있기 때문에 성능이 빠르다는 부분도 이 문서를 보면 대략적으로 이해되리라 생각한다.

의견 추가하기

연관태그

← 목록으로