Hầu hết các ngôn ngữ chức năng sử dụng danh sách được liên kết làm cấu trúc dữ liệu bất biến chính. Tại sao danh sách, và không ví dụ như cây? Cây cũng có thể sử dụng lại các đường dẫn, và thậm chí cả danh sách mô hình.
Hầu hết các ngôn ngữ chức năng sử dụng danh sách được liên kết làm cấu trúc dữ liệu bất biến chính. Tại sao danh sách, và không ví dụ như cây? Cây cũng có thể sử dụng lại các đường dẫn, và thậm chí cả danh sách mô hình.
Câu trả lời:
Bởi vì danh sách đơn giản hơn cây. (Bạn có thể thấy điều này một cách tầm thường bởi thực tế rằng một danh sách là một cây thoái hóa, trong đó mỗi nút chỉ có một con duy nhất.)
Danh sách khuyết điểm là cấu trúc dữ liệu đệ quy đơn giản nhất có thể có kích thước tùy ý.
Guy Steele lập luận trong quá trình thiết kế ngôn ngữ lập trình Pháo đài rằng đối với các tính toán song song lớn trong tương lai, cả cấu trúc dữ liệu và luồng điều khiển của chúng ta phải có hình cây với nhiều nhánh, không phải tuyến tính như hiện tại. Nhưng hiện tại, hầu hết các thư viện cấu trúc dữ liệu cốt lõi của chúng tôi được thiết kế với xử lý tuần tự, lặp lại (hoặc đệ quy đuôi, điều đó không thực sự quan trọng, chúng giống nhau), không phải xử lý song song.
Lưu ý rằng, ví dụ như trong Clojure, có cấu trúc dữ liệu được thiết kế dành riêng cho thế giới song song, phân tán, "mây" ngày nay, thậm chí các mảng (được gọi là vectơ trong Clojure), có lẽ là cấu trúc dữ liệu "tuyến tính" nhất trong số chúng, thực sự được triển khai như cây.
Vì vậy, trong ngắn hạn: một danh sách khuyết điểm là cấu trúc dữ liệu đệ quy liên tục đơn giản nhất có thể và không cần phải chọn một "mặc định" phức tạp hơn. Những thứ khác tất nhiên có sẵn dưới dạng tùy chọn, ví dụ Haskell có mảng, hàng đợi ưu tiên, bản đồ, heap, treap, cố gắng và mọi thứ bạn có thể tưởng tượng, nhưng mặc định là danh sách khuyết điểm đơn giản.
data Tree a = Leaf a | Branch a (Tree a) (Tree a)
. Điều này củng cố lập luận "đơn giản" của bạn.
Sequence
hoặc Scala Vector
), nhưng không sử dụng cây khi chúng chỉ cần đọc vì chúng có thể đạt được điều đó trong thời gian không đổi thực sự (ví dụ: Haskell's Vector
hoặc F # thông qua .Net's ImmutableArray
)
pmap
ping trên một vectơ trong Clojure vẫn truy cập từng phần tử một cách tuần tự; cấu trúc cây của vectơ thường được ẩn khỏi người dùng cuối.
Trên thực tế, những danh sách đó là cây! Bạn có các nút có hai trường car
và cdr
, có thể chứa nhiều nút hoặc lá như vậy. Điều duy nhất mà làm cho những cây vào danh sách, là quy ước để giải thích sự cdr
liên kết như liên kết tới nút tiếp theo trong danh sách tuyến tính, và các car
liên kết như giá trị của nút hiện hành.
Điều đó nói rằng, tôi đoán rằng sự phổ biến của các danh sách được liên kết trong lập trình chức năng có liên quan đến sự phổ biến của đệ quy trên phép lặp. Khi cấu trúc lặp duy nhất của bạn trong tay là đệ quy (đuôi-), bạn muốn các cấu trúc dữ liệu dễ sử dụng với điều đó; và danh sách liên kết là hoàn hảo cho điều đó.