見出し画像

関数型プログラミング事始め (39) 評価(1)

関数型プログラミングがはじめての方へ贈る入門の書
前節:状態 次節:評価(2)
参考書:
・五味 弘「はじめてのLisp関数型プログラミング」技術評論社(2016)
・大山口 通夫、五味 弘「プログラミング言語論」コロナ社(2008)
・五味 弘「関数型プログラミングと数学(ITと数学)」技術評論社(2021)

関数型プログラムはどのようにすればいいのでしょうか。関数型プログラムも当然ながらプログラムなので、通常の評価方法は適用できます。例えば、プログラム断片の大きさや個数、結合手段や結合数、変数や引数などで評価しています。
これに加えて関数型プログラムは何をどこを評価するのでしょうか。関数型と言えば、副作用が大きな問題になり、それに影響する状態や変数がキーになります。そして関数型の強みである組み合わせ自由なプログラミング環境が与えられるかどうかで評価することになります。

4章. 関数型プログラムの評価

ここでは関数型プログラムの評価を見ていくことにします。この関数型プログラムはプログラムとしてみた場合、優れているのか、それとも劣っているのかを見ていくことにします。

4.1 通常のプログラムとしての評価

関数型プログラムも、当然ながら通常のプログラムなので、通常のプログラムに対する評価方法があり、まずそれを見ていきます。

(1) 関数のサイズ

関数などのプログラム断片のサイズはプログラムを評価する指標のひとつになります。

大きすぎる関数は、内容を理解するのを妨げ、バグの原因になります。小さすぎる関数は、関数呼び出しが多くなり、効率が悪くなります。

プログラム断片のサイズはプログラミング言語の仕様や文化に大きく依存します。このためサイズの目安は各言語によって決めるようにした方がいいでしょう。例えば再帰プログラミングのLispでは関数のサイズは小さくなり、平均では10行未満になります。なお再帰プログラミングでない繰り返しプログラミングのLispでは関数のサイズは大きくなります。

関数サイズのデータとしては平均サイズと閾値を超えた関数の個数を収集することにします。平均はプログラムの評価に使い、閾値を超えた関数個数はリスク分析に使います。

例えば再帰プログラミングのLispプログラムでは、平均は10行未満、閾値は25行程度にしています。ちなみに繰り返しプログラミングのLispプログラムでは再帰の2倍程度になるでしょう。

ただしこの平均関数サイズは、プログラムの規模に(本来は依存しないはずなのに)依存します。大規模なプログラムで1個1個の関数サイズが大きくなるのは関数の個数が爆発的に多くなるのを危惧するというのがあるのかもしれません。一言で言えば、「ちょこまか」と作っていられないということです。このため、規模別で関数サイズの評価をするのが現実的でしょう。

(2) 関数の個数

関数の個数が多すぎると管理が大変になり、それがバグの原因になります。それよりも個数が多いということはコピペプログラミング(関数をコピーして、少しだけ変更するプログラミング)の疑いが出てきます。

関数の個数は関数のサイズと負の相関があり、全体のプログラムの大きさ(規模)に正の相関があります。このため、単純な関数の個数だけではプログラムを評価することは難しいでしょう。このため、関数個数ではなく(1)の関数サイズのメトリクスに任せましょう。

なお関数の個数は評価のために収集するのではなく管理のために収集することになります。

(3) 引数の個数

引数の個数はプログラムを評価する指標のひとつになります。多すぎる引数はプログラムを見にくくし、少ない引数はグローバル変数が多く使われている危険があります。

関数型プログラミングではグローバル変数を忌避するので、逆に引数個数は多くなります。それでも関数型プログラミングでは引数の個数は8個以内を閾値にします。

引数個数が多くなるときは、即値型のデータを引数にするのではなく、それを要素とする構成型のデータを引数にして、引数をまとめることで引数個数を減らすことができます。

ただし構成型のデータでは副作用を生じる可能性があるため、値を変更する要素があるデータをコピーや追加型にすることが必要になります。詳細はイミュータブルの節を参照してください。

(4) グローバル変数の個数

グローバル変数の個数はプログラムの評価をする材料のひとつになります。多すぎる変数はプログラムを見にくくし、バグの原因になります。少なすぎる変数は一つ一つの変数が巨大化・複雑化している可能性があります。これもバグの原因になります。

グローバル変数は副作用が生じやすく、バグの原因になります。これは関数型プログラミング言語の教えですが、一般の言語でもこの考え「グローバル変数は必要悪、いや、悪魔の所業」は浸透しています(個人の感想が多少入っているかもしれない)。

「グローバル変数は禁止!」と言いたいですが、通常のプログラムの評価としては1000行辺り1個は許可します(なぜか上から目線)。

(5) ローカル変数の個数

ローカル変数のうち、引数については前述していますので、ここでは引数ではないローカル変数について見ていきます。

ローカル変数はグローバル変数と比較して有効範囲と活動している時間が制限されていますので、副作用の危険性も小さくなります。しかし小さくなっているだけで、副作用の危険性がないわけではありません。この意味では「ローカル変数は小悪魔のいたずら」です。

なおローカル変数はその有効範囲内でブロックするのが正解です。この意味では(宣言が必要な言語では)ローカル変数の宣言はそれを使用する直前にするべきです。とにかく、ローカル変数は小悪魔的な必要悪なので、閉所に閉じ込めるのが正義です。

そしてローカル変数の個数の閾値としては、あまり公開されたデータはありませんが、迷ったときの「マジックナンバー7」という都市伝説がありますので、ローカル変数は7個以内というのがあります。

なおこのローカル変数の個数は関数サイズに依存します。このため関数サイズのデータでプログラム評価を代替させている場合もあります。(手抜きではありません、たぶん)

(予告) (6) 関数の構造

今回は通常のプログラムにおける評価指標を見てきました。次回も通常のプログラムにおける評価指標として、プログラムの構造やその他の評価指標を見ていくことにします。


いいなと思ったら応援しよう!

五味弘
よろしければサポートをお願いします!