連載
» 2012年03月15日 00時00分 公開

Scalaの基本的なコレクション4タイプと制御構文・例外スケーラブルで関数型でオブジェクト指向なScala入門(3)(2/2 ページ)

[中村修太,クラスメソッド株式会社]
前のページへ 1|2       

Scalaの条件分岐「if」

 条件分岐は「if」を用います。条件式の結果がtrueかどうかに基づいて処理を分岐します。構文は、以下のようになっています。

if(条件式)[trueの時の処理] else [falseのときの処理]

 実際には、以下のようにします。

scala> val x = 0
x: Int = 0
 
scala> if(x == 0) println("x = 0")
x = 0
 
scala> if(x == 1) println("x = 1") //何も出力されない

 Javaと違って、Scalaのifは最後に評価された値を返します。下の例では、xの評価結果で処理を分岐しています。

scala> val result = if(x == 0) "x is zero" else "x is one"
result: java.lang.String = x is zero

 処理に複数の式を記述したい場合は式を「{}]で囲みます。また、elseの後にifをネストさせることも可能です。

scala> val result = if(x == 0) {
     |   println("x == 0")
     |   "x is zero"
     | } else if(x == 1) {
     |   println("x == 0")
     |   "x is one"
     | } else {
     |   println("x != 0 && x != 1")
     |   "x is " + x
     | }
x == 0
result: java.lang.String = x is zero

 もし条件式がfalseになり、elseがなかった場合、返される値はUnit(Javaでいう「void」)の唯一の値、「()」になるので注意してください。

scala> val x = 1
x: Int = 1
 
scala> val result = if(x == 0) "x is Zero"
result: Any = ()

Scalaの繰り返し「for」

 Scalaでは、繰り返し処理を行うとき、「for」を使用することがとても多いです。整数カウンタを用いたシンプルな繰り返しだけではなく、コレクションの精査フィルタリングなど、さまざまな処理を容易に実現できます。

 for式の構文は、以下が一般的です(※処理に複数の式を記述したい場合は式を「{}]で囲みます)。

for(
 [ジェネレータ]
 [フィルタ] ※任意
) 式

 まずはシンプルなfor式を見てみましょう。ジェネレータ部分は、繰り返し処理を行うために要素を順番に返すための記述です。「item <- listItems」のようにして、コレクションから要素を1つずつ取り出します(※ちなみに、「<-」は全角文字の「←」でも代用可能です)。

 下の例ではlistItemsリストから要素を1つずつ取り出し、printlnで出力しています。

scala> val listItems = List("Scala","Java","Ruby")
listItems: List[java.lang.String] = List(Scala, Java, Ruby)
 
scala> for(item <- listItems) println("item = " + item)
item = Scala
item = Java
item = Ruby

 for式のフィルタを使用すれば、処理前に要素をチェックできます。フィルタはfor式のジェネレータの後にifを追加することで実現できます。評価結果がtrueになれば、式を実行できます。

 下の例では、要素が4文字より大きければtrueとなり、printlnが実行されます。なお、フィルタは複数記述することも可能です。

scala> for(
     |   item <- listItems //ジェネレータ
     |   if item.length > 4 //フィルタ
     | ) println("item = " + item)
 
item = Scala

 これまでの例では、コレクションから要素を出して使用後に捨てていました。しかし、for式で加工した結果を保持しておきたい場合もあります。そういった場合、「yield」を使用して新しいコレクションを生成できます。

 下の例では、コレクションの各要素に対して文字列を付加し、その要素を持つ新しいListを生成しています。

scala> val resultList = for(item <- listItems) yield "I use " + item
resultList: List[java.lang.String] = List(I use Scala, I use Java, I use Ruby)
 
scala> resultList
res33: List[java.lang.String] = List(I use Scala, I use Java, I use Ruby)

 なお、yieldを記述する位置は、式の直前に書かなければなりません。式を「{}」で囲っている場合、その直前に記述する必要があるので注意してください。

 Scalaのfor式は非常に便利で多機能です。今回は基本的な部分のみ紹介しましたが、さらに詳細を知りたい方はScalaの言語仕様書をご確認ください。

Scalaの繰り返し「while」「do-while」

 Scalaでは、「while」でも繰り返し処理を記述できます。

 whileの構文は以下のようになっており、Javaと同じように、条件式と式の部分を持ち、条件式の結果がtrueの間処理を繰り返します。

while(条件式) 式

 下の例では変数「i」を定義してカウンタとして使用しています。

scala> var i = 0
i: Int = 0
 
scala> while(i < 10) {
     |   println("i = " + i)
     |   i += 1
     | }
i = 0
i = 1
……
i = 9

 またScalaでは、条件式にかかわらず少なくとも処理を1回は実行する、「do-while」文も使えます。do-whileの構文は以下のようになっており、条件式の評価は式が1度実行された後になります。

do { 式 } while (条件式)
scala> var i = 0
i: Int = 0
scala> do {
     |  println("i = " + i)
     |  i += 1
     | } while (i < 10)
i = 0
i = 1
……
i = 9

 コレクションの精査はforを使用する方が便利ですが、条件が変更されるまで繰り返し処理を行いたい場合などにはwhileを使用した方がシンプルに記述できることがあります。状況に応じて使い分けましょう。

Javaに似ているScalaの例外処理

 Scalaの例外処理は、Javaと同じく「try」「catch」「finally」を使えます。tryブロック内で発声した例外をcatchブロックで捕まえ、finallyブロックで終了処理を記述します。

 例外処理の構文は、以下のようになっています。

try {
  式
} catch {
  case 変数:例外クラスの型 => 例外処理の式
  ……
} finally {
  式
}

 Scalaでは、catchブロックで例外の型に応じて処理を分岐でき、そのためにcaseを使用します。また、finallyブロックは例外発生の有無にかかわらず実行されます。

 下の例ではtryブロック内で、わざと例外を発生させてcatchブロックで捕まえています。catchブロックでは-1を返しており、result変数に値が返されています。そして最後にfinallyブロックが実行されます。

scala> val result = try {
     |   "a".toInt
     |  } catch {
     |   case e:NumberFormatException => {
     |     println("exception!")
     |     -1
     |  } finally {
     |     println("finally!")
     |  }
exception!
finally!
result: Int = -1

 なお、例外を発生させるには、「throw」を使います。

scala> throw new Exception("throw Exception!")
java.lang.Exception: throw Exception!
	at .<init>(<console>:8)
……

補足 Scalaの例外は「非チェック例外」

Javaと違い、Scalaの例外はすべて「非チェック例外」です。例えば、Javaで「java.io.FileWriter」を使用する場合には、try-catchで囲うかthrowsを宣言しなければコンパイルエラーになりますが、Scalaの場合はエラーになりません。また、JavaのライブラリをScalaから使用する場合も同様です。

ただ、あくまでもエラーにならないだけなので、必要があれば例外を適切にcatchし、処理を行ってください。例外についての基本は、記事「プログラマの宿命! 例外とエラー処理を理解する」の「実行時に発生する例外」をご覧ください。


次回は、いよいよScalaの「関数」!

 今回はScalaのコレクションに始まり、条件分岐や繰り返しの制御構文、例外処理についても紹介しました。本記事で使用したListやMapなどのコレクションや制御構文は今後もよく使用するので、覚えておいてください。

 次回は、Scalaの関数について紹介します。

筆者紹介

クラスメソッド株式会社

中村修太(なかむら しゅうた)

クラスメソッド勤務の新しもの好きプログラマーです。昨年、東京から山口県に引っ越し、現在はノマドワーカーとして働いています。好きなJazzを聴きながらプログラミングするのが大好きです。



前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。