関数型プログラミング事始め (3) 変数の苦難
関数型プログラミングがはじめての方へ贈る入門の書
前節:効能 次節:配列の苦難
参考書:
・五味 弘「はじめてのLisp関数型プログラミング」技術評論社(2016)
・大山口 通夫、五味 弘「プログラミング言語論」コロナ社(2008)
・五味 弘「関数型プログラミングと数学(ITと数学)」技術評論社(2021)
1.3 関数型プログラミングの苦難=その原因
前節では関数プログラミングの効能を紹介しました。しかしその関数型プログラミングは難しいと言われています。数学者みたいな感じの人が白衣を着て、プログラミングすると思われています(もちろん一部の人だけです)。
もちろん、そんなことはありませんが、それでも関数型プログラミングは難しいところがあります。ここでは難しいところ、苦難の道を紹介していきます。
(1) 変数は使えない? - 破壊的代入の禁止
関数型プログラミングは副作用(*1)を許しません。この副作用の原因のひとつが変数です。しかしすべての変数が悪いのではなく、破壊的代入(*2)を伴う変数が駄目なのです。
(*1) 関数型プログラミング事始め (1) 定義 参照
(*2) 変数に格納されている値を変える代入、既存の値がなくなる代入
例. 「関数型プログラミング事始め (1) 定義」の1.1の例(再掲)
int publicVariable = 0;
int fun(int x){
publicVariable = publicVariable + x;
return publicVariable;
}
この「publicVariable = publicVariable + x;」が変数に破壊的代入をしています。これが副作用の原因になります。
関数型プログラミングでは「変数が使えない」という噂があります。これは間違いで、正しくは「破壊的代入をする変数が使えない」ということになります。逆に言えば、値を変更しない変数は使えます。例えば、一時的に値を格納する変数は使えます。
グローバル変数については関数型プログラミング以外でも、使用は推奨されていません。グローバル変数は破壊的代入を行うために使われるので、副作用が生じます。だから、グローバル変数は使わないようにしましょう。
なおローカル変数でも同様の副作用は生じますが、その影響範囲はローカル変数の有効範囲内だけです。
# ローカル変数なら少しだけ使ってもいいです(現実主義者)。いや駄目だ(原理主義者)。
(考察)オブジェクト指向プログラミングの欠点「グローバル変数がいっぱい」
オブジェクト指向プログラミングでは、普通にプログラムを作ってしまうとグローバル変数がいっぱいになります。手続き型プログラミングよりも多いくらいです。
例えば、Javaのフィールド変数(メンバ変数、インスタンス変数)はメソッド関数におけるグローバル変数です。Javaプログラムではこのフィールド変数をいっぱい使いがちです。
なおフィールド変数よりも質の悪いのが、スタティック変数(クラス変数)です。この変数は極悪非道で、クラス内だけでなく、複数のクラスにまたがって悪影響を及ぼす悪者の変数です。
(弁解)グローバル変数を使いたい
このようなグローバル変数をなぜ使うのでしょうか。それは便利だからです。一瞬で状態を変えることができます。これがあまりにも便利です。だから使うのです。
でも使い過ぎに注意してください。1個のプログラムにグローバル変数は1個までです。それ以上多いと健康を害します。
(対策)グローバル変数は引数に繰り込み
破壊的代入を伴う変数が使えないですが、それを引数に繰り込めば大丈夫です。「関数型プログラミング事始め (1) 定義」の1.1の例であれば、以下のようになります。
例.
int fun(int x, publicVariable){
return publicVariable + x;
}
(次回予告) (2) 配列の苦難
次回は今回の関数型プログラミングの難しさの続きになり、配列が使えない?をお送ります。変数が使えないに続いて配列ですが、これは今回と同じ原因の破壊的代入がキーになります。続きは次回で。
参考:プログラミング言語はどれがお得?(前編)|五味弘 (note.com)
参考:プログラミング言語はどれがお得?(後編)|五味弘 (note.com)