計算途中の値に名前を付けると処理が読める
プログラムは、入力、計算、判断、出力を順に進めます。その途中では、入力された文字、現在の得点、繰り返した回数、計算結果などを覚えておかなければなりません。値を直接並べるだけでは、それぞれが何を表すのか分かりにくくなります。そこで、値に price や count のような名前を付けて扱います。
例えば、price に120、count に3を入れ、total に price * count の結果を入れるとします。後から価格だけが変わっても、計算の形はそのまま利用できます。また、total という名前から、その値が合計を表すことも読み取れます。このように変数は、値を覚えるだけでなく、アルゴリズムの各段階が何をしているのかを人間に伝える役割も持ちます。
変数名の規則は言語ごとに異なります。規則を満たすだけでなく、x より itemCount のように目的が分かる名前を選ぶと、処理を読み直すときや誤りを探すときに役立ちます。
宣言・初期化・代入・参照は別の操作
変数を扱う流れは、いくつかの操作に分けて考えられます。宣言は、使用する変数の名前をプログラムに示すことです。初期化は、使い始めるときの値を設定すること、代入は値を変数に結び付けること、参照は現在の値を読み出して計算や表示に使うことです。宣言と同時に初期値を代入できる言語もあれば、明示的な宣言を必要としない言語もあります。
初期化されていない変数の扱いも、言語によって違います。エラーになることもあれば、特別な値として扱われることもあります。「値の設定前に読み出していないか」を確かめ、回数や合計なら0など、目的に合った初期値を決めると処理が明確になります。
実行中の値はメモリを利用して保持されます。ただし、高水準の言語では、通常、具体的なメモリアドレスを指定する必要はありません。変数名を通して値を扱えるためです。
変数に入れられる値の種類を「型」が決める
整数、実数、文字列、真偽値など、値には種類があります。この種類をデータ型と呼びます。変数を宣言するときに型を指定する言語では、決められた型に合わない値を代入するとエラーになります。一方、代入された値に応じて型を扱う言語もあります。どちらの場合でも、数値の加算と文字列の連結のように、型によって可能な操作や結果が変わります。
一つの変数は一つの値を扱うのが基本ですが、複数の値をまとめたデータも一つの変数から利用できます。例えば、複数の得点を順序付きでまとめるときには配列を使います。変数はそのまとまりを指す名前となり、添字を使って個々の要素を読み書きします。単独の値と値の集まりを使い分けることで、同じ処理を繰り返し適用しやすくなります。
同じ変数名でも見える場所には境界がある
変数を利用できるプログラム上の範囲をスコープと呼びます。関数の中で宣言した変数は、その関数の外からは参照できないようにする言語が一般的です。このような局所的な変数をローカル変数と呼び、広い範囲から利用できるものをグローバル変数と呼びます。細かな規則は言語ごとに異なります。
範囲を狭くすると、別の処理への思いがけない影響を防ぎやすくなります。二つの関数がそれぞれ count というローカル変数を持っていても、別々の変数として扱えます。一つのグローバル変数を多くの処理が書き換えると、値が変化した場所を追いにくくなります。
変数には、利用できる期間である寿命もあります。関数を呼び出している間だけ存在する変数もあれば、プログラムの実行中ずっと値を保つ変数もあります。再帰では同じ関数が重なって呼び出されますが、各呼び出しのローカル変数は区別して管理されます。スコープが「どこから見えるか」、寿命が「いつまで存在するか」を表す点が違いです。
「名前の付いた箱」では説明しきれない参照の共有
変数を箱にたとえると、代入や参照の基本は理解しやすくなります。しかし、すべての変数が値そのものを独立した箱に収めているとは限りません。配列やオブジェクトのようなデータでは、変数がデータのある場所を示す参照を保持する仕組みがよく使われます。
二つの変数が同じデータへの参照を持つと、一方の変数を通して内容を変更した結果が、もう一方から見ても反映されることがあります。これは二つの箱へ同じ内容を複製した状態ではなく、二つの名前が同じ対象を指している状態です。ただし、代入時に値を複製するか参照を共有するか、どの値を変更可能にするかは言語やデータ型によって異なります。
値を受け渡す関数では、この違いが重要です。関数内で引数の内容を変えたとき、呼び出し元のデータまで変わるかを理解していないと、予想外の結果につながります。複合的なデータでは参照の可能性を確かめる必要があります。
記号「=」が数学の等号とは限らない理由
数学の式 x = x + 1 は、通常の等式として読むと成立しません。しかし、多くのプログラミング言語では、これは「現在の x に1を足し、その結果を x へ代入する」という順序のある処理を表せます。左辺と右辺が常に等しいと主張するのではなく、右辺を先に計算して保存内容を更新する命令だからです。
比較と代入を区別するため、代入に =、等しいかの比較に == を使う言語があります。一方で、別の記号を採用する言語もあるため、記号の意味は使用する言語の規則で確認します。この違いは、数学の変数とプログラムの変数が同じ名前でも役割まで同一ではないことを示しています。
一度設定した後は再代入できない名前を用意する仕組みもあります。値を変えない意図を示すと、誤った書き換えを防ぎやすくなります。関数型プログラミングでは状態変化を抑え、入力から出力を求める関係として処理を組み立てる考え方が重視されます。変数を見るときは、名前と値がどう結び付いているかも大切です。