Більшість функціональних мов використовують пов'язані списки як їх первинну незмінну структуру даних. Чому списки, а не, наприклад, дерева? Дерева також можуть повторно використовувати шляхи та навіть списки моделей.
Більшість функціональних мов використовують пов'язані списки як їх первинну незмінну структуру даних. Чому списки, а не, наприклад, дерева? Дерева також можуть повторно використовувати шляхи та навіть списки моделей.
Відповіді:
Тому що списки простіші за дерева. (Ви можете бачити це банально за тим, що список - це вироджене дерево, де кожен вузол має лише одну дитину.)
Список мінусів - це найпростіша можлива рекурсивна структура даних довільного розміру.
Гай Стіл стверджував під час проектування мови програмування Fortress, що для масово паралельних обчислень майбутнього, і наші структури даних, і наш потік управління повинні мати деревоподібну форму з декількома гілками, а не лінійними, як зараз. Але поки що більшість наших основних бібліотек структури даних були розроблені з послідовною, ітеративною обробкою (або хвостовою рекурсією, це насправді не має значення, вони однакові), а не паралельною обробкою.
Зауважте, що, наприклад, у Clojure, структури даних яких були розроблені спеціально для паралельного, розподіленого, "похмурого" світу сьогодні, навіть масиви (звані вектори в Clojure), мабуть, найбільш "лінійна" структура даних з усіх насправді реалізовані як дерева.
Отже, коротше: список мінусів є найпростішою можливою стійкою рекурсивною структурою даних, і не було потреби вибирати складніший "за замовчуванням". Інші, звичайно, доступні як варіанти, наприклад, Haskell має масиви, черги пріоритетів, карти, купи, трепи, спроби та все, що ви могли собі уявити, але за замовчуванням - це простий список мінусів.
data Tree a = Leaf a | Branch a (Tree a) (Tree a)
s. Це підсилює ваш аргумент "простоти".
Sequence
або Scala Vector
), але не використовують дерева, коли вони потребують лише читання, оскільки вони можуть досягти цього в реальному постійному часі (наприклад, Haskell's Vector
або F # via .Net's ImmutableArray
)
pmap
пінг над вектором у Clojure як і раніше отримує доступ до кожного елемента послідовно; деревна структура вектора, як правило, прихована від кінцевого споживача.
Власне, ці списки - це дерева! У вас є вузли з двома полями car
і cdr
, які можуть містити більше таких вузлів або листя. Єдине , що робить ці дерева в списки, є конвенція інтерпретують по cdr
посиланню в якості посилання на наступний вузол в лінійному списку, і car
посилання в якості значення поточного вузла.
Зважаючи на це, я думаю, що поширеність зв'язаних списків у функціональному програмуванні пов'язана з поширеністю рекурсії над ітерацією. Коли ваш єдиний цикл циклу під рукою - це (хвоста) рекурсія, ви хочете, щоб структури даних, які були зручними для використання з цим; і пов'язані списки ідеально підходять для цього.