noyのブログ

プログラミングとかゲームとか

コップ本でScala入門 - 2 配列、リストなど

配列

関数型なのに配列を!?

string a[3];
a[0] = "ab";
a[1] = "cd";
a[2] = "ef\n";
for(int i = 0; i < 3; i++){
    cout << a[i];
}
val a = new Array[String](3)
a(0) = "ab"
a(1) = "cd"
a(2) = "ef\n"
for(i <- 0 to 2){
    print(a(i))
}

生成するインスタンスの構成を設定する事をパラメーター化という。
上記の例では、Stringという型パラメーター、3という値パラメーターを設定している。

for式にある to はメソッドである。
詳しく書くと、こうなる。

for(i <- (0).to(2))

数値はIntオブジェクトである。
toというメソッドを呼び出し、Intオブジェクトである2を渡している。
もっというと、すべての演算がメソッド呼び出しである。

val num = Array(1,2,3)

このような初期化もできる。

リスト

配列は変更可能(ミュータブル)であるが、
Scalaのリストは変更不能(イミュータブル)である。
※可変リストもある

val a = List(1,2)
val b = 0 :: a
val c = b ::: a
println(b)
println(c)
出力
List(0, 1, 2)
List(0, 1, 2, 1, 2)

セミコロンで整数をくっつけたり、リストをくっつけたりできる。
Listメソッドにはいろいろある。

その中でも関数言語感を感じるmapの紹介を。

val list = List(1,2,3,4)
println(list.map(a => a * a))
出力
List(1, 4, 9, 16)

リストの各要素に関数を適用する。

タプル

イミュータブルなコンテナオブジェクト。
異なる型の要素を持つ事ができる。

val pair = (1, "a")
val tuple = (1, "a", 3.1)
println(pair._1)
println(tuple._3)
println(tuple)
出力
1
3.1
(1,a,3.1)

ここで、tupleの型はTuple3[Int, String, Double]になっている。

0-indexではないが、これは静的に型付けされたタプルは1から始まるという伝統のためである。

scala> val t = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)                                             
t: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22)

要素をたくさん増やしたくなるが、23個以上はエラーが返ってくる。

集合とマップ

Scalaにはミュータブルなコレクションとイミュータブルのコレクションが区別されている。

イミュータブルなset

var set = Set(1,2,3)
set += 4
println(set.contains(4))
出力
true

setに要素を追加するには+演算子を使う。

イミュータブルなmap

val map = Map(1 -> "a", 2 -> "b", 3 -> "c")
println(map(2))
出力
b

イミュータブルなmapに要素を追加しようとするとエラーが返る。
追加したい場合は、ミュータブルなmapを使う。

test.scala:3: error: value += is not a member of scala.collection.immutable.Map[Int,String]               
Expression does not convert to assignment because receiver is not assignable.                                       
map += (4 -> "a")

Scalaプログラマーに求められる態度

val、イミュータブルオブジェクト、副作用のないメソッドを優先する。
理由があるなら、var、ミュータブルオブジェクト、副作用のあるメソッドを使う。

Haskellは後者を許さない(はず)。一度Haskellに挑戦した事があるが、簡単なコードを書くのにもかなり苦労した。
その点Scalaは融通が利いて良いが、常にJavaとして書いてしまうと関数型言語の考えが身につかないので、うまく使い分ける必要がありそう。

まとめ

  • 配列が使える
  • コレクションはイミュータブルとミュータブルが区別される
  • val、var、イミュータブル、ミュータブルは使い分ける


コップ本でScala入門 - 1 Scalaとは / if、for - noyのブログ
次 ないです