static foreach
タプル章で、コンパイル時のforeachについて説明した。コンパイル時のforeachは、コンパイル時にループを反復し、各反復を個別のコードとして展開する。例えば、タプルを反復する次のforeachループがある。
コンパイラは、ループを次のような同等のコードに展開する:
コンパイル時のforeachは非常に強力であるが、場合によっては、その一部の特性が適さない場合もある。
- コンパイル時
foreachでは、ループの展開ごとにスコープが追加される。上記のiとmember変数のように、これにより、複数のスコープでシンボルを使用しても多重定義エラーが発生しない。これは一部のケースでは望ましいが、1つの反復展開されたコードが他の反復のコードを使用できなくなる。 - コンパイル時の
foreachは、タプル(AliasSeqの形式のテンプレート引数を含む)でのみ機能する。例えば、次の配列リテラルの要素はコンパイル時に既知であるにもかかわらず、ループは常に実行時に実行される(これはまさに望ましい動作である場合もある)。
- 通常の
foreachと同様に、コンパイル時のforeachは関数内でのみ使用できる。例えば、モジュールスコープやユーザー定義の型定義内では使用できない。
エラー: 宣言が必要、foreachではない
- コンパイル時の
foreachでは、ループ本体内のbreakおよびcontinue文が、コンパイル時のループの反復自体に影響を与えるのか、それとも展開されたコードの一部となるのかが明確ではない場合がある。
static foreachは、より強力なコンパイル時機能で、より詳細な制御を提供する:
static foreachは、コンパイル時に計算できるあらゆる範囲の要素(1..10のような数値範囲を含む)で使用できる。例えば、Rangesの章で説明したFibonacciSeriesの範囲と、数値が偶数であるかどうかを判断する関数がある。
上記のループは、以下の同等のコードに展開される:
static foreachモジュールスコープで使用できる。static foreach各反復に個別のスコープを導入しない。例えば、次のループは、モジュールスコープで関数の2つのオーバーロードを定義している。
上記のループは、以下の同等のコードに展開される:
breakまた、static foreachループ内のcontinue文は、明確にするためにラベルが必要だ。例えば、次のコードは、switch文内のcase句を展開(生成)する。各case句の下にあるbreak文は、関連するswitch文をラベルで指定する必要がある。
上記のループが展開されると、switch文は次のコードと同等になる。