기능적 언어로 선택된 데이터 구조가 나열되는 이유는 무엇입니까?


45

대부분의 기능적 언어는 링크 된 목록을 기본 불변 데이터 구조로 사용합니다. 왜 나무가 아닌리스트인가? 트리는 경로와 모델 목록도 재사용 할 수 있습니다.



10
@gnat-이것은 그 질문과 중복 되지 않습니다 . 이 질문에 대한 정답은 본질적으로 "불변의 링크 된 목록이 업데이트 된 목록과 원본 목록 사이에 꼬리를 공유 할 수 있기 때문"이며,이 질문에 대한 배경의 일부로 지적되는 답변입니다.
Jules

9
설명의 한 가지 요점은 "언어"(추상 프로그래밍 개념)가 "연결된 목록"(해당 개념의 특정 구현)과 구별된다는 점입니다. 프로그래밍 언어의 사양은 구현과는 다릅니다. "기능적 언어가 왜 목록 (추상 프로그래밍 개념)을 주요 데이터 구조로 사용합니까?"라는 질문 "기능적 언어 X, Y 및 Z의 공통 구현이 링크 된 목록을 주요 데이터 구조로 사용하는 이유는 무엇입니까?"라는 질문과 미묘하지만 근본적으로 매우 다릅니다.
RM

scala Vector (트리로 구현 됨)는 List stackoverflow.com/questions/6928327/ 보다 약간 선호됩니다 . 실제로 대부분의 사람들은 여전히 ​​내가 본 것으로부터 Lists를 사용합니다.
Akavall

스칼라에서 Functional Programming 강좌를 수강하고 나무가 많은 LOT을 사용했습니다. 예를 들어 목록이 더 간단합니다. 트리는 성능 문제에 사용됩니다. 변경 불가능한 목록에 요소를 추가 할 때와 같이 오래된 트리의 일부를 재사용하여 변경 불가능한 트리를 작성할 수 있습니다.
Borjab

답변:


56

목록은 나무보다 단순하기 때문입니다. (리스트는 모든 노드가 하나의 자식만을 갖는 퇴화 트리라는 사실에 의해 간단하게 볼 수 있습니다.)

단점 목록은 임의의 크기의 가장 간단한 재귀 데이터 구조입니다.

Guy Steele은 Fortress 프로그래밍 언어를 설계하는 동안 미래의 대규모 병렬 계산을 위해 데이터 구조와 제어 흐름이 현재와 같이 선형이 아닌 여러 가지로 트리 모양이어야한다고 주장했습니다. 그러나 당분간 대부분의 핵심 데이터 구조 라이브러리는 병렬 처리가 아닌 순차적 반복 처리 (또는 꼬리 재귀, 실제로는 중요하지 않음)를 염두에두고 설계되었습니다.

참고 예를 들어 누구의 데이터 구조를 특별히 설계되었다 Clojure의에 대한 오늘날의 "흐린"세계, 심지어 배열 (Clojure의 호출 벡터), 아마 그들 모두의 데이터 구조 "선형"가장이되어 분산 병렬, 실제로 으로 구현 나무.

요약하자면, 단점 목록은 가능한 가장 간단한 영구 재귀 데이터 구조이며 더 복잡한 "기본"을 선택할 필요가 없습니다. Haskell에는 배열, 우선 순위 대기열, 맵, 힙, 가두기, 시도 및 상상할 수있는 모든 것이 있지만 옵션은 옵션으로 사용할 수 있지만 기본값은 간단한 단점 목록입니다.


10
예, Clojure 벡터는 트리로 구현되지만 표준 바이너리가 아닌 해시 배열 매핑 된 시도 라는 점에 유의하십시오 data Tree a = Leaf a | Branch a (Tree a) (Tree a). 이것은 당신의 "단순성"주장을 강화합니다.
wchargin

1
FWIW Clojure의 영속 벡터는 (@wchargin이 다소 복잡한 것으로 지적) 트리로 구현되어 실제로 병렬 작업이 아닌 임의의 요소에 대한 빠른 액세스 (대규모가 큰 로그) 액세스 및 업데이트 (불변 부분이 일부를 처리 함) 정도). 다른 FP 언어는 두 가지 모두 (예 : Haskell Sequence또는 Scala Vector) 를 원할 때 동일한 선택 (때로는 다른 종류의 나무가 있음)을 선택 하지만 실제 일정한 시간에 달성 할 수 있으므로 읽기만하면 트리를 사용하지 않습니다 (예 : Vector.Net을 통한 Haskell 또는 F # ImmutableArray)
badcook

1
예를 들어 pmapClojure의 벡터를 ping하면 여전히 각 요소에 순차적으로 액세스합니다. 벡터의 트리 구조는 일반적으로 최종 사용자로부터 숨겨집니다.
badcook

5

사실, 그 목록 나무입니다! 당신은 두 개의 필드와 노드가, car그리고 cdr더 같은 노드, 또는 잎을 포함 할 수있는. 이러한 트리를 목록으로 만드는 유일한 것은 링크를 선형 목록의 다음 노드에 대한 링크로 해석 하고 cdr링크를 car현재 노드의 값으로 해석 하는 규칙 입니다.

즉, 함수형 프로그래밍에서 링크 된 목록의 유병률은 반복에 대한 재귀의 유병률과 관련이 있다고 생각합니다. 현재 유일하게 반복되는 구조가 (꼬리) 재귀 인 경우,이를 사용하기 쉬운 데이터 구조가 필요합니다. 그리고 링크 된리스트는 그에 완벽합니다.


5
언어에 따라 다릅니다. 물론 cons 셀을 사용하여 LISP와 비슷한 트리를 구현할 수 있지만 Haskell에서는 완전히 별도의 구조가 필요합니다. 또한 대부분의 기능적 언어에는 꼬리 재귀보다 많은 루프 구성이 있습니다. 예를 들어, Haskell 핵심 라이브러리는 접힘 (왼쪽 및 오른쪽), 스캔, 트리 탐색, 키의 키 및 값 반복, 기타 여러 전문 구조를 제공합니다. 물론, 그들은 배후에서 재귀로 구현되지만 사용자는 그것들을 작동시키기 위해 그것에 대해 생각할 필요조차 없습니다.
Jules

@Jules 그럼에도 불구하고, 함수형 프로그래밍은 LISP와 같은 언어에 의해 개발되어 크게 영향을 받았습니다. 분명히, 후드 아래에서 배열을 사용 하여이 목록 반복을보다 효율적으로 만들거나 목록의 특성을 숨기는 구문 설탕을 추가 할 수 있지만 순수한 기능 프로그래밍은 할 수 있고하지 않습니다. 또한 Haskell은 최신 언어 (LISP보다 32 세 더 젊음)이며 순수한 기능적 스타일에 다른 아이디어, 구문 설탕 등을 추가합니다. 내가 하스켈을 판단하여 함수형 프로그래밍을 판단, 생각은 조금 판단하여 믹서를 판단처럼 thermomix ...
cmaster

2
@cmaster는 Haskell이 더 젊지 만 여전히 27 세이며 많은 언어 (Python, Java 및 C #을 포함하여 거의 영향을 미치지 않음)에 영향을 미쳤습니다. LISP의 기능적 프로그래밍을 판단하는 것은 ALGOL의 명령형 프로그래밍을 판단하는 것과 같습니다. 둘 다 인식 할 수없는 것보다 먼 길을 왔습니다. 승인. Lisp은 여전히 ​​관련성이 있지만 '주류'라고 생각하지 않으며 ML 유형을 포함하여 나중에 많은 통찰력을 그리워합니다.
Maciej Piechotka

1
전체 트리를 터치하려는 경우 명시 적 스택없이 단일 링크 트리 테일을 재귀 적으로 또는 반복적으로 처리 할 수 ​​없으므로 테일 재귀와 관련이 없다고 생각합니다.
k_g

@MaciejPiechotka Python, Java 또는 C #은 기능적 언어로 볼 수 없으며 기능적 프로그래밍에서 영감을 얻은 필수 기능을 추가해야합니다. 상태를 변경 한 후에는 기능적 프로그래밍이 아니라 명령형 영역에 단단히 들어갑니다. 그러나 LISP가 주류가 아니라는 점에 동의합니다.
cmaster
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.