オプション的なありさま
「存在しない」ことをどう定義するべきか
null
ある変数が空であることを示したい場合、どのような手段が適正だろうか。
空と言うのはゼロの数値のことではあらず、そのままの意でそこに何もないことを指す。
その場合、直接ハードウェアを操作する機械語が基準であり、その規則からどれだけ離れているかで高さを表現する。機械語に近い言語であるから低級言語と呼ぶ。逆は高級言語。 [annotation: 直接ハードウェアを操作する機械語が基準であり、その規則からどれだけ離れているかで高さを表現する。機械語に近い言語であるから低級言語と呼ぶ。逆は高級言語。] であればnull
ポインタを利用することが多いだろう。
null
ポインタは、メモリの番地を指し示す仕組みであるポインタの中でも、どこでもない場所を指す特殊なポインタである。
これにより、数値を格納する変数だが数値は格納されておらず空である、のような状態を表すことができる。
しかしながら、これをわざわざ利用するような低級言語では、その変数がnull
であるかどうかをプログラマの責任で管理しなければならない。
その変数がnull
であるかどうかは、ロジックを精査するか、実行してみなければわからないのだ。
安全策を取る必要のある箇所では、いわゆるnull
チェックによって対応することになる。
条件分岐文を使用して、その変数がnull
ポインタを指し示していないかを調べる必要があるわけだ。
この安全策を取るか取らないかは、プログラマの一存に委ねられるものであり、前述の責任に掛ることになる。
この構造は明らかに不健全であり、後発のプログラミング言語において改善されることになる。
あるとない
特にある変数に格納できる型が固定であることを前提とする言語群。整数型の値を格納している変数に文字列型の値を格納することはできない。逆は動的型付き言語。 [annotation: ある変数に格納できる型が固定であることを前提とする言語群。整数型の値を格納している変数に文字列型の値を格納することはできない。逆は動的型付き言語。] の分野において顕著だろう。
それには様々な呼び名があるが、null
チェックを内包したシステムであることがほとんどだ。
すなわち、中身がnull
である(可能性がある)ことをコードから読み取れ、かつ変数として操作するならば中身がある保証がなされている必要があるのである。
こうした安全な空型は、必須じみたnull
チェックの煩雑さがあれど、広く市民権を得ていると思われる。
このうちの1つにバリアント型と言うものがある。近く連載の方でも扱うだろう。
これは場合分けを示す型であり、要はこれで中身の型と空と言う概念のどちらかが格納されていることを示せば良いと言う発想である。
バリアント型において、中身を保証する仕組みは全ての場合分けを記述する必要があると言うものだ。
手間はかかるが、より厳密なコード表現になるため、(おそらく)関数型言語由来の機能であるが近年の言語では界隈を問わず採用されやすい。
――――では、このバリアント型とやらで解決する問題なのだな、で済むかに思えるが、技術と言うものは有用になればなるほど細かな部分が気になり、そのたびに新たな視点を生むものなのであった。
下記は架空のプログラミング言語で定義されたバリアント型Opt
であり、ユーザが任意に付け合わせることのできる型A
が存在する場合と空である場合の2パターンを持つ。
variant Opt with A
{
Exist A,
Null,
}
ここでExist
とNull
は単なるラベルであり、識別以上の意味を持たない。
これを任意の型A
を含むオプション型と便宜上呼ぶことにする。
これを利用することで、この言語のありとあらゆる型をオプション型にすることができると言う寸法だ。
――――しかしながら、このバリアント型はあまりにも表現力が強い。何でも表現できてしまうのである。
variant Process
{
StepA X,
StepB Y,
StepC Z,
NoStep,
}
上記のバリアント型Process
はそれぞれ特定の型X
、Y
、Z
を含む場合とNoStep
ラベルで示された空の場合で構成されている。
これも安全な空型であるのはわかるだろう。
だが、これは先程定義したオプション型を利用していないのだ。
つまり、バリアント型を使用して安全な空型を定義する際、無数の新たな安全な空型が生まれうるのである。
こうなるとバリアント型を使用して記述されたプログラムはしっちゃかめっちゃかである。
先程のProcess
型は下記のようにも定義可能だ。
variant Steps
{
StepA X,
StepB Y,
StepC Z,
}
def Process = Opt with Steps
ここでdef
はリネーム、長い型名に別名を付けるものであるが、それを踏まえてこれら2つのProcess
型は同じものを表現していないだろうか。
残念ながら、どちらの場合がコーディング的に正しいかを述べる主張は確認したことがない。
少なくともどちらかに統一したいものだが、バリアント型の表現力故にそもそもどこからが同じジャンルなのかもはっきりさせにくい。
まだ答えは思い付かないが、この思想を残しておきたい。