上でコメントしたように、これは特に良い並べ替え方法ではありません (Scala コードを理解していると仮定しますが、理解していない可能性があります)。これは、何をしているように見えるかを OCaml に翻訳したものです。
let insertion_sort l =
let add1 sortedl x =
let le, gt = List.partition ((>=) x) sortedl
in
le @ [x] @ gt
in
List.fold_left add1 [] l
FP コードをしばらく書くと、折り畳みが非常に自然になります。目的は、データ構造 (リストなど) の一連の要素を既知の順序 (左端など) で処理しながら、処理中に渡される状態を維持することです。最も単純なケース (ここのように) では、状態が最終的な答えでもあります。それ以外の場合は、最終的な回答とともに追加の状態を保持する必要があります。そのような場合、最後に最終的な答えを抽出します。
これを言うべきではないかもしれませんが、折り畳みはfor(;;)
、ループで変更する予定のすべての状態をカプセル化することを除いて、C ファミリーのステートメントに似ています。このように、これは適切に制御された形式の反復です。
対応は次のようになります。
for(state = S, x = first(D); more(D); x = next(D)) { state = E(state, x) }
fold_left (fun state x -> E state x) S D
変更された状態をカプセル化する規則は、通常、慣れると非常に役立つことがわかります。折りたたんだ関数 (上記の add1 など) は、他の多くの状況で役立つことがよくあります。これは、折りたたみの構造がその場所で一般的に役立つ関数を必要とするためです。
特に、fold 関数には、データ構造をトラバースする方法に関するすべての知識が含まれていることに注意してください。折りたたまれた関数は、各要素をどう処理するかを知る必要があるだけです。したがって、他のコードを変更することなく、データ構造 (およびフォールド) を自由に変更できます。また、同じ関数 (add1
上記) を異なるデータ構造で使用することもできます。