基本的なリスト操作を実装しましょう。
関数型言語では、lengthやmap、reduceのようなリスト操作がよく使われます。既存の関数を使わずに、一連の基本的なリスト操作を実装してみましょう。
実装する操作の正確な数や名前は、既存の名前との衝突を避けるため、トラックによって異なります。ただし、一般的には次のような操作を実装します。
append(2つのリストが与えられたとき、2つ目のリストのすべての要素を1つ目のリストの末尾に追加します)。concatenate(一連のリストが与えられたとき、すべてのリストの要素を1つの平坦なリストにまとめます)。filter(述語とリストが与えられたとき、predicate(item)がTrueになるすべての要素のリストを返します)。length(リストが与えられたとき、その中にある要素の総数を返します)。map(関数とリストが与えられたとき、すべての要素にfunction(item)を適用した結果のリストを返します)。foldl(関数・リスト・初期アキュムレーターが与えられたとき、各要素を左からアキュムレーターに畳み込みます(reduce))。foldr(関数・リスト・初期アキュムレーターが与えられたとき、各要素を右からアキュムレーターに畳み込みます(reduce))。reverse(リストが与えられたとき、元の要素をすべて逆順に並べたリストを返します)。なお、畳み込み関数(foldl、foldr)に引数を渡す順序は重要です。
私たちが書く解答がmainスクリプトではないのは、これまでの演習で初めてです。ここでは、私たちの関数を呼び出すほかのスクリプトにsourceで読み込まれるライブラリを書きます。
この演習では、nameref変数を使う必要があります。そのためには、Bashのバージョン4.0以上が必要です。MacOSのデフォルトのBashを使っている場合は、別のバージョンをインストールする必要があります。詳しくはBashのインストールを参照してください。
namerefを使うと、変数を関数に_参照渡し_できます。こうすると、関数の中で変数を変更でき、呼び出し元のスコープでも更新された値を使えます。次に例を示します。
prependElements() {
local -n __array=$1
shift
__array=( "$@" "${__array[@]}" )
}
my_array=( a b c )
echo "before: ${my_array[*]}" # => before: a b c
prependElements my_array d e f
echo "after: ${my_array[*]}" # => after: d e f a b c