2012年7月14日土曜日

[Scale] 数値指定のfor文について

for (i : Int <- 1 to 5) { ... }

以前、for文の記事 を書いたとき、なぜ、わざわざ java の for ( int i=0; i<10; i++) と異なる構文を用意したかと思っていたが、 実はこういうことだった。

val range : Range = 1 to 5.
for (i : Int <- range ) { ... }

Range 型オブジェクトに対する 拡張 for 文だった。
(「拡張」 for 文というか、結局 Scala の for 文はこの形式だけ)

Scala では「1」や「2」などの primitive もオブジェクト扱いなのでメソッドが呼び出せる。
値を返すメソッドは中置記法で書けるので一見気が付きにくい。

for (i : int <- 1 to 5) { ... }   も

for (i : int <- 1.to(5)) { ... }

と書けば Int 型のメソッドが実行されて何かができていることが一目でわかる。
どうも Scala の中にはこういう罠があちこちにあるような気がする・・・



Intクラスのドキュメンテーションによれば、

 *  There is an implicit conversion from [[scala.Int]] => [[scala.runtime.RichInt]]
 *  which provides useful non-primitive operations.

とうことなので実際に to 等のメソッドが用意されているのは RichInt クラスになる。
RichInt クラスで定義されている Range 型を返すメソッドを見てみると、

  def until(end: Int): Range = Range(self, end)
  def until(end: Int, step: Int): Range = Range(self, end, step)
  def to(end: Int): Range.Inclusive = Range.inclusive(self, end)
  def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(self, end, step)

がある。
ステップ指定付きの to() を使ってみよう。

for (i : Int <- 1 to (10,2)) print(i);

13579

until() が Range 型を返しているのに対して、 to() は Range.Inclusive を返している。
Range 型では終端値は含まないのに対して、その派生型である Range.Inclusive は終端値を含むという違いがある。

for (i : Int <- 1 to 5) print(i);
println;
for (i : Int <- 1 until 5) print(i);

12345 1234



0 件のコメント:

コメントを投稿