ほとんどの関数型言語は、リンクリストを主要な不変データ構造として使用します。なぜ木ではなくリストなのか?ツリーはパスを再利用したり、リストをモデル化することもできます。
ほとんどの関数型言語は、リンクリストを主要な不変データ構造として使用します。なぜ木ではなくリストなのか?ツリーはパスを再利用したり、リストをモデル化することもできます。
回答:
リストはツリーよりも単純だからです。(リストが縮退ツリーであり、すべてのノードに子が1つしかないという事実から、これを簡単に見ることができます。)
短所リストは、任意のサイズの可能な限り単純な再帰的データ構造です。
Guy Steeleは、Fortressプログラミング言語の設計中に、将来の超並列計算のために、データ構造と制御フローの両方が、現在のように線形ではなく、複数の分岐を持つツリー型であるべきだと主張しました。しかし、当面の間、コアデータ構造ライブラリのほとんどは、並列処理ではなく、逐次反復処理(または末尾再帰、実際には問題ではなく、同じこと)を念頭に置いて設計されています。
例えば、今日の並列分散「クラウド」世界向けにデータ構造が特別に設計されたClojureでは、おそらく最も「線形」なデータ構造である配列(Clojureではベクトルと呼ばれる)でさえ実際に実装されていることに注意してください木。
つまり、要するに、短所リストは可能な限り単純で永続的な再帰データ構造であり、より複雑な「デフォルト」を選択する必要はありませんでした。もちろん、その他のオプションもオプションとして利用できます。たとえば、Haskellには配列、優先度キュー、マップ、ヒープ、トレープ、試行など、想像できるすべてのものがありますが、デフォルトは単純なconsリストです。
data Tree a = Leaf a | Branch a (Tree a) (Tree a)
。これにより、「単純さ」の議論が強化されます。
Sequence
やScala など)に同じ選択を行います(異なる種類のツリーをVector
使用することもあります)が、読み取りのみが必要な場合はツリーを使用しないでください。 Haskell Vector
または.Net経由のF#ImmutableArray
)
pmap
、Clojureのベクターに対するpingは、引き続き各要素に順次アクセスします。通常、ベクターのツリー構造はエンドユーザーからは見えません。
実際、これらのリストはツリーです!2つのフィールドを持つノードがあり、car
およびにはcdr
、そのようなノードまたはリーフをさらに含めることができます。それらのツリーをリストにする唯一のことは、リンクを線形リスト内の次のノードへのリンクとして解釈し、cdr
リンクをcar
現在のノードの値として解釈する規則です。
そうは言っても、関数型プログラミングにおけるリンクリストの普及率は、反復を超える再帰の普及率にリンクしていると思います。手元にあるループ構造のみが(末尾)再帰である場合、それで使いやすいデータ構造が必要です。リンクリストはそのために最適です。