for式

Scala の for 式は、ほかのプログラミング言語よりも機能が豊富だ。まずは簡単な例から見てみよう。

scala> for (x <- 1 to 3) {
| println("x = " + x)
| }
x = 1
x = 2
x = 3

見ての通り x を 1 から 3 まで繰り返しているけど、このカッコの中の x <- 1 to 3 をジェネレータと呼ぶ。1 to 3 は 1 から 3 まで(3 を含む)の範囲を表す式でこれを順に x に代入するものだ。ジェネレータは複数あってもいい。

scala> for (x <- 1 to 3; y <- 1 until 3) {
| println("x = " + x + " y = " + y)
| }
x = 1 y = 1
x = 1 y = 2
x = 2 y = 1
x = 2 y = 2
x = 3 y = 1
x = 3 y = 2

今度の例では x と y のジェネレータを使っている。1 until 3 というのは 1 から 2(3を含まない)の範囲を表している。

ジェネレータには条件を付けることができる。次の例では、x と y が等しくない場合だけを抽出している。

scala> for (x <- 1 to 3; y <- 1 until 3 if x != y) {
| println("x = " + x + " y = " + y)
| }
x = 1 y = 2
x = 2 y = 1
x = 3 y = 1
x = 3 y = 2

for 式は、コレクションの要素を1つずつたどっていくこともできる。いわゆる foreach のような使い方だ。次の例ではリストの要素を順に出力している。

scala> for (e <- List("A", "B", "C", "D", "E")) {
| println(e)
| }
A
B
C
D
E

さらに、for 式ではコレクションから新しいコレクションを作ることもできる。

scala> for (e <- List("A", "B", "C", "D", "E")) yield {
| "Pre" + e
| }
res5: List[String] = List(PreA, PreB, PreC, PreD, PreE)

ここでのポイントは、ブロック式の前についている yield キーワードだ。yield をつけることで単に繰り返すのではなく、新しいコレクションを作ってくれる。yield キーワードを使ったこの形を for-comprehension と呼ぶことがある。

while式

while 式も構文は普通。注意しなきゃいけないのは、カッコの中の条件式が Boolean 型じゃないといけないことくらいだ。

scala> while (i <= 10) {
| println("i = " + i)
| i = i + 1
| }
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10

while 式も式なので値を持つ。ただし、必ず Unit 型の値 () になる。上の例ではわかりにくいので、変数に代入してみよう。

scala> var b = while (i <= 10) {
| println("i = " + i)
| i = i + 1
| }
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10
b: Unit = ()

このとおり。