名前スコープ
名前は、定義されたポイントからそのスコープが終了するポイントまで、およびそのスコープに含まれるすべてのスコープ内でアクセス可能である。この点において、すべてのスコープは名前スコープを定義する。
名前は、そのスコープの終了点を超えては利用できない:
inner
は、if
条件内のスコープで定義されているため、そのスコープ内でのみ利用可能だ。一方、outer
は、外側のスコープと内側のスコープの両方で利用可能だ。
同じ名前を内側のスコープで定義することはできない:
スコープは文に関連付ける必要はない。関数 (およびその他のほとんどの構文) 内の自由な中括弧のペアで定義することができる。
ただし、このような関連付けられていないスコープは、モジュールスコープ(ソースコードの最上位レベル)では定義できない:
最初の使用に最も近い位置での名前の定義
これまでのすべてのプログラムでそうしてきたように、変数は最初の使用前に定義する必要がある:
このコードがコンパイラで受け入れられるためには、number
はwriteln
で使用される前に定義されている必要がある。定義する行数は制限されていないが、変数は最初の使用場所にできるだけ近い場所で定義することが良いプログラミング慣行とされている。
ユーザーから入力された数値の平均を表示するプログラムで、これを確認しよう。他のプログラミング言語に慣れているプログラマーは、スコープの先頭で変数を定義することに慣れているかもしれない:
上記のコードと、変数を後で定義し、各変数が実際にプログラムに参加し始める以下のコードを比較しよう:
すべての変数をスコープの先頭で定義する方が構造的に見栄えが良いように見えるかもしれないが、可能な限り遅く定義するメリットがいくつかある:
- 速度:変数の定義はプログラムに小さな速度のコストを追加する傾向がある。Dではすべての変数が初期化されるため、変数をスコープの先頭で定義すると、後で時々しか使用されない場合でも常に初期化され、リソースを無駄にする。
- ミスするリスク:変数の定義と使用の間のすべての行は、プログラミングミスをするリスクが高くなる。この例として、一般的な名前
length
を使用する変数を考えてみよう。この変数は、他の長さを持つ変数と混同され、最初に使用される行に到達する前に誤って使用されてしまう可能性がある。その行にようやく到達した時点で、その変数はもはや望ましい値を持っていないかもしれない。 - 可読性:スコープ内の行数が増えるほど、変数の定義がソースコードの上部に遠ざかり、プログラマーが定義を確認するためにスクロールバックする必要が生じる可能性が高くなる。
- コードのメンテナンス:ソースコードは絶えず変更および改善されている。新しい機能が追加されたり、古い機能が削除されたり、バグが修正されたりする。これらの変更により、一連の行をまとめて新しい関数に抽出する必要がある場合がある。
その場合、変数をそれらを使用する行の近くに定義しておくと、それらを一致したグループとして移動しやすくなる。
例えば、このガイドラインに従った上記の2番目のコードでは、
if
文内のすべての行を、プログラム内の新しい関数に移動することができる。一方、変数が常に先頭で定義されている場合、一部の行を移動する必要が生じた場合、それらの行で使用されている変数を1つずつ特定する必要がある。