基本的なリスト操作を実装しましょう。
関数型言語では、lengthやmap、reduceのようなリスト操作がよく使われます。既存の関数を使わずに、一連の基本的なリスト操作を実装してみましょう。
実装する操作の正確な数や名前は、既存の名前との衝突を避けるため、トラックによって異なります。ただし、一般的には次のような操作を実装します。
append(2つのリストが与えられたとき、2つ目のリストのすべての要素を1つ目のリストの末尾に追加します)。concatenate(一連のリストが与えられたとき、すべてのリストの要素を1つの平坦なリストにまとめます)。filter(述語とリストが与えられたとき、predicate(item)がTrueになるすべての要素のリストを返します)。length(リストが与えられたとき、その中にある要素の総数を返します)。map(関数とリストが与えられたとき、すべての要素にfunction(item)を適用した結果のリストを返します)。foldl(関数・リスト・初期アキュムレーターが与えられたとき、各要素を左からアキュムレーターに畳み込みます(reduce))。foldr(関数・リスト・初期アキュムレーターが与えられたとき、各要素を右からアキュムレーターに畳み込みます(reduce))。reverse(リストが与えられたとき、元の要素をすべて逆順に並べたリストを返します)。なお、畳み込み関数(foldl、foldr)に引数を渡す順序は重要です。
Javaでは、クラスメソッドよりもインスタンスメソッドを使うことがベストプラクティスとされています。ただし、関数をstaticにするのが完全に適切な場合もあります。Javaのクラスは変更に対して閉じているため(つまり、RubyやJavaScriptなど他の言語のように、定義の外からクラスにメンバーを追加することはできません)、クラスに直接新しい振る舞いを追加することはできません。では、それでもある型に振る舞いを定義したいときはどうすればよいのでしょうか? この場合の定石は、ユーティリティメソッドを書くことです。
この種のメソッドを集めたものは、よく「ユーティリティクラス」と呼ばれます。JREに含まれるそのようなクラスの例には、ArraysやCollectionsがあります。
この演習では、Listにmap()、reduce()、filter()などのメソッドを持たせたいと考えます。しかしListにはそれらがないので、静的メソッドを使います。
foldLeftメソッドとfoldRightメソッドは「フォールド」関数です。これは関数型プログラミングの世界では広く知られた概念ですが、オブジェクト指向の世界ではあまり知られていません。折り畳みに関するWikipediaのページで、一般的な背景とシグネチャと実装のヒントを参照してください。