「配列」とは同じ型のデータを複数持てるオブジェクトです。要素の順序を保持でき、「0」を先頭とする添字で任意の要素にアクセスできます。
Scalaで配列を使用するには、「Array」クラスを使います。Arrayは要素の型を「型パラメータ」(Javaでいう「Generics(ジェネリック型)」)として受け取って初期化します(※「型パラメータ」については、今後の連載で紹介します)。
例えば、Intの配列を定義するなら、「Array[Int]」とします。
配列のサイズは決まっていて、要素の値が決まっていない場合、配列の初期化は「Array[型名](配列サイズ)」と定義します。要素の値も決まっている場合、「Array[型名](要素1の値,要素2の値……)」と定義します。
scala> val a1 = new Array[Int](10) a1: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) scala> val a2 = Array(1,2,3) //型パラメータを指定しなくても、型推論によってArray[Int]と判断される a2: Array[Int] = Array(1, 2, 3)
配列内の要素を取得/設定するためには、「()」で添字を指定します。また、「length」メソッドを使用すれば配列のサイズを取得できます。
scala> a2(0) = 100 //配列の要素に値を設定 scala> val num = a2(1) //配列の要素を取得 num: Int = 2 scala> a2.length //配列の長さを取得 res24: Int = 3 scala> a2 //配列内容を表示 res25: Array[Int] = Array(100, 2, 3)
なお、Scala配列はJavaの配列と対応しています(Scalaの「Array[Int]」はJavaの「int[]」として表現できます)。
なぜScalaでは配列要素を取得や設定するために「()」を使用しているのでしょうか。
実は、配列に対して「()」で要素指定したとき、実際にはArrayに定義されたメソッドを呼び出しているのです。
例えば、配列の値を取得する「a(0)」という式は、Arrayに定義されている「apply」メソッドの呼び出しです。
また、値を設定する「a(0) = 10」という式は、Arrayに定義されている「update」メソッドの呼び出しです。
scala> a2(1) //値の取得 res31: Int = 2 scala> a2.apply(1) //値の取得 res32: Int = 2 scala> a2(1) = 10 //値の設定 scala> a2.update(1,10) //値の設定
この配列に対する「()」での要素指定が、apply/update呼び出しの「糖衣構文」(プログラミング言語において、読み書きのしやすさのために導入される構文。「シンタックスシュガー」ともいう)となっているため、このような記述が可能になっているのです。
Scalaでは、このような糖衣構文がいくつかあり、うまく使用すれば簡潔な記述ができます。
Scalaでは、演算子は、すべてメソッドです。例えば、「1 + 2」という式を見てみましょう。この「+」は、Intクラスが持つメソッドなのです。
Scalaはメソッドが1つの引数を取る場合、ピリオドと「()」を省略できます。そのため、メソッド呼び出しが演算子と同じように見えるのです。
scala> 1 + 2 res8: Int = 3 scala> 1 .+(2) //1の後に「.」を付けると、Doubleと判断されるので、スペースを入れる res9: Int = 3
また、引数を取らないメソッドはピリオドを付けずに呼び出し可能です。
Scalaでの「算術演算子」「関係演算子」「論理演算子」の意味は、Javaの演算子とまったく同じです。一般的によく使用される演算子を表5に示します。
演算子 | 例 | 説明 |
---|---|---|
+ | x + y | 加算 |
- | x - y | 減算 |
* | x * y | 乗算 |
/ | x / y | 除算 |
% | x % y | 剰余 |
+= | x += y | x = x + y |
-= | x -= y | x = x - y |
*= | x *= y | x = x * y |
/= | x /= y | x = x / y |
%= | x %= y | x = x % y |
&& | a && b | aとbが両方trueの場合にtrue |
|| | a || b | aとbが、どちらかtrueの場合にtrue |
< | a || b | aがbより小さい場合にtrue |
<= | a <= b | aがb以下の場合にtrue |
> | a > b | aがbより大きい場合にtrue |
>= | a >= b | aがb以上の場合にtrue |
表5 一般的な演算子 |
ただしJavaと違い、インクリメントとデクリメントは存在しません。「+=」「-=」演算子を使用してください。
2つのオブジェクトが等しいかどうか比較したい場合、等しいかどうか判定する「==」、等しくないかどうか判定する「!=」を使用しますが、比較演算子については少し注意が必要です。
例えば、Javaでは「==」「!=」の比較は、プリミティブ型の場合は値同士の比較となり、参照型の場合は各オブジェクトの参照が同じインスタンスを指しているのかどうかを比較します。
参照型で値が等しいかどうかを判定したい場合は「equals()」メソッドを使用して比較する必要がありました。Scalaでは、IntでもStringでも「==」「!=」で値が等しいかどうかを比較できます。
scala> val a = 1 a: Int = 1 scala> val b = 1 b: Int = 1 scala> a == b res11: Boolean = true scala> val s1 = "hello" s1: java.lang.String = hello scala> val s2 = "hello" s2: java.lang.String = hello scala> s1 == s2 res12: Boolean = true
最後に、Scalaにおけるコメントの記述方法について紹介します。Scalaでは、Javaと同じように、1行だけ有効なコメント(単一行コメント)と、複数行に有効なコメント(複数行コメント)があります。
単一行コメントは「//」で始まり、行末までがコメントです。そして、複数行コメントは「/*」で始まり、「*/」が来るまでがコメントです。ただ、複数行コメントはJavaなどとは違い、ネストできます。
scala> //コメント scala> /* 複数行 | 有効なコメント */ scala> /* 複数行 | 有効なコメントは | /* ネストすることが */ | できます。 */
今回は、Scalaの基本構文について紹介しました。基本データ型や演算子についてはJavaと同じ部分が多く、Javaの経験のある方は、なじみやすかったと思います。
次回は、制御構文について紹介します。
中村修太(なかむら しゅうた)
クラスメソッド勤務の新しもの好きプログラマーです。昨年、東京から山口県に引っ越し、現在はノマドワーカーとして働いています。好きなJazzを聴きながらプログラミングするのが大好きです。
Copyright © ITmedia, Inc. All Rights Reserved.