Większość języków funkcjonalnych używa list połączonych jako podstawowej niezmiennej struktury danych. Dlaczego listy, a nie np. Drzewa? Drzewa mogą również ponownie wykorzystywać ścieżki, a nawet listy modeli.
Większość języków funkcjonalnych używa list połączonych jako podstawowej niezmiennej struktury danych. Dlaczego listy, a nie np. Drzewa? Drzewa mogą również ponownie wykorzystywać ścieżki, a nawet listy modeli.
Odpowiedzi:
Ponieważ listy są prostsze niż drzewa. (Widać to trywialnie dzięki temu, że lista jest zdegenerowanym drzewem, w którym każdy węzeł ma tylko jedno dziecko.)
Lista wad to najprostsza możliwa rekurencyjna struktura danych o dowolnym rozmiarze.
Guy Steele argumentował podczas projektowania języka programowania Fortress, że w przypadku masowo równoległych obliczeń przyszłości, zarówno nasze struktury danych, jak i nasz przepływ sterowania powinny mieć kształt drzewa z wieloma gałęziami, a nie liniowymi, jak są teraz. Ale na razie większość naszych podstawowych bibliotek struktur danych została zaprojektowana z myślą o przetwarzaniu sekwencyjnym, iteracyjnym (lub rekurencyjnym), a nie przetwarzaniu równoległym.
Należy pamiętać, że na przykład w Clojure, której dane struktury zostały zaprojektowane specjalnie dla równoległego, rozproszonego, „mętny” dzisiejszego świata, a nawet tablice (zwane wektory w Clojure), prawdopodobnie najbardziej „liniowy” struktury danych z nich wszystkich, są faktycznie realizowane jako drzewa.
Krótko mówiąc: lista wad to najprostsza możliwa stała struktura danych rekurencyjnych i nie było potrzeby wybierania bardziej skomplikowanego „domyślnego”. Inne są oczywiście dostępne jako opcje, np. Haskell ma tablice, kolejki priorytetowe, mapy, stosy, pułapki, próby i wszystko, co można sobie wyobrazić, ale domyślnie jest to prosta lista wad.
data Tree a = Leaf a | Branch a (Tree a) (Tree a)
. To wzmacnia twój argument „prostoty”.
Sequence
lub Scali Vector
), ale nie używają drzew, gdy potrzebują tylko czytać, ponieważ mogą to osiągnąć w czasie rzeczywistym (np. Haskell's Vector
lub F # via .Net's ImmutableArray
)
pmap
Pingowanie nad wektorem w Clojure nadal uzyskuje dostęp do każdego elementu sekwencyjnie; struktura drzewa wektora jest na ogół ukryta przed użytkownikiem końcowym.
W rzeczywistości te listy to drzewa! Masz węzły z dwoma polami car
i cdr
, które mogą zawierać więcej takich węzłów lub liści. Jedyną rzeczą, która sprawia, że te drzewa na listach, jest konwencja, aby zinterpretować ten cdr
link jako link do następnego węzła na liście liniowej, a car
link jako wartość bieżącego węzła.
To powiedziawszy, myślę, że przewaga połączonych list w programowaniu funkcjonalnym jest związana z przewagą rekurencji po iteracji. Gdy jedynym dostępnym zapętlonym konstruktem jest rekursja (ogona), potrzebujesz struktur danych, które są z tym łatwe w użyciu; i połączone listy są do tego idealne.