関数型プログラミング事始め (7) 高階関数の苦難
関数型プログラミングがはじめての方へ贈る入門の書
前節:ラムダの苦難 次節:遅延評価の苦難
参考書:
・五味 弘「はじめてのLisp関数型プログラミング」技術評論社(2016)
・大山口 通夫、五味 弘「プログラミング言語論」コロナ社(2008)
・五味 弘「関数型プログラミングと数学(ITと数学)」技術評論社(2021)
(5) 高階関数の苦悩
関数型プログラミングでは、関数も数値や文字列のような普通のデータと同じように扱えます。数値や文字列が関数の引数やその返値、変数の値になるとのと同じように、関数も関数の引数や返値、変数の値になれます。
関数を引数や返値にする関数は高階関数(higher-order function)と呼ばれています。関数の引数が関数を引数にしない普通の関数である場合は、2階関数と呼びます。そして関数の引数になる関数も引数に関数を取る(複雑怪奇、魑魅魍魎な関数)なら、3階関数です。
でも健康のために3階関数の適用は止めた方がいいでしょう。3階関数は頭が混乱し、何よりプログラムを読むのに目が疲れます。
でも高階関数、ここでは2階関数は便利です。プログラムが抽象的に作成でき、汎用性のあるプログラムができます。それに何より、如何にも関数型プログラミングぽくなりますので、見栄を張ることができます。
この節は「高階関数の苦悩」の節ですから、あまり褒め殺しぽく記載するのは止めにして、なにより苦悩の話をすることにします。褒め殺しは後述することにします。
(考察)関数はデータ
関数はデータというのは、別に関数型プログラミング言語の特許ではありません。例えば、C言語の関数ポインタはC言語のデータとして扱えます。アセンブラ言語ではそもそもデータとアセンブラコードの区別はありません。
関数型プログラミングでは、ラムダ式を使います。ラムダ式は変数束縛(関数引数のようなもの)とプログラムコードから構成されるもので、関数名がない匿名関数です。
関数がデータであるということは、そのデータとしての関数実行のタイミングは動的に変更でき、また関数は普通のデータであるので、その関数を動的に変更できます。つまり、関数はいつ実行されるかが不明であり、その関数そのものも動的に変わるかもしれないのです。幽霊みたいなやつです。
このように関数がデータであることから、動的に実行が変更されるので、プログラムの了解性は著しく難しくなります。これが関数型プログラミングが難しいと言われる原因のひとつです。
(考察)高階関数は定型的に
高階関数は手作りすると、前節のように了解性が困難になるので、典型的な使い方をするといいでしょう。関数型プログラミングでは、言語仕様で定義されている高階関数のライブラリ関数を使うのがいいでしょう。
例えば、引数全部に引数の関数を適用するマップ関数(map)や、関数をマッピングした結果をまとめるリデュース関数(reduce)などのライブラリ関数を使います。
(次回予告) (6) 評価戦略の苦難
次回は今回の高階関数を使った関数の評価(実行)戦略の予定です。引数や返値の関数をいつどのように実行するかの戦略についてになります。普通の関数呼び出しは引数の実行は左側優先・内側優先ですが、関数型プログラミングではこの戦略が動的に変更できます。でも面倒です。苦難です。という話になります。
参考:プログラミング言語はどれがお得?(前編)|五味弘 (note.com)
参考:プログラミング言語はどれがお得?(後編)|五味弘 (note.com)