Beginning Scala programming

初心者ぺちぱーがGitHubでScalaレッスンを始めたぞ。まずは練習問題を解きながら、Scalaを覚えてみようと思う。教科書はいわゆるコップ本だ。

Scalaスケーラブルプログラミング第2版
作者
Martin Odersky
Lex Spoon
Bill Venners
出版社
インプレスジャパン
発売日
2011-09-27
メディア
単行本(ソフトカバー)
価格
¥ 4,968
Scala逆引きレシピ (PROGRAMMER’S RECiPE)
作者
竹添 直樹
島本 多可子
出版社
翔泳社
発売日
2012-07-03
メディア
単行本(ソフトカバー)
価格
¥ 3,456

Lessen1: loop

練習問題はここから拝借した。色々ネタがあって面白い。

Hello World![改行]を5回表示させてください。

print(或いはprintf,cout等)を5回コピーすれば当然可能ですが、ループ構文(for,while等)を利用して、print等は1回の使用にとどめてみてください。

注釈にもある通りだが、こんなコードが欲しいわけじゃない。

bad answer
def fiveTimes() {
println("Hello World!")
println("Hello World!")
println("Hello World!")
println("Hello World!")
println("Hello World!")
}

まずは基本的な制御構造であるループを覚えよう。Scalaで使えるループは3つある。forwhile、それからdo-whileだ。あ、コップ本の"第07章 組み込みの制御構造"を開いて欲しい。

// for
for (i <- 1 to 3) {
// hoge
}
// while
while (a != 0) {
// hoge
}
// do-while
do {
// hoge
} while (x != 0)

whiledo-whileの違いは他言語と同様に、繰り返しの条件が、ループの最初で評価されるのか、ループの最後で評価されるのか、という違いだ。

for式はちょっと見慣れない格好をしているが、これはコレクションの反復を実行する、という意味になるそうだ。1 to 3はRange型のオブジェクトを返す。rubyの1..3みたいなやつだきっと。ruby知らないけど。pythonのrange(1, 3)みたいなやつだ。python忘れたけど。phpのrange(1, 3)みたいなイメージだな。あんまり使った事ないけどね。

for式を使ってprintlnしてみると、こんな感じだ。

def forFiveTimes(): Unit = {
for (i <- 1 to 5) {
println("Hello World!")
}
}

結果型のUnitはいわゆるvoidと同じ意味らしい。forの中身は一行しかないので、中括弧{}は書かなくても、ちゃんと動く。

def forFiveTimes(): Unit = {
for (i <- 1 to 5) println("Hello World!")
}

さらに、メソッドが単一の結果式を計算するだけなら、中括弧{}を省略できる、とコップ本p.081に書いてある。

def forFiveTimes(): Unit = for (i <- 1 to 5) println("Hello World!")

なんか随分すっきりした書き方だな。でももうちょっと短く書ける。

def forFiveTimes() = for (i <- 1 to 5) println("Hello World!")

右辺を代入してるように見えるから、ちょっと違和感があるね。この書き方。printlnしてるだけだから、戻り値はないわけだし。コップ本p.081には、こう書いてある。

結果型がUnitのメソッドは、副作用を生じさせるために実行される。副作用は、一般にメソッドの外にある状態の変更や、入出力アクションの実行だと定義される。このようなメソッドでは、結果型と等号を省略し、メソッド本体を中括弧で囲むという表現方法もある。この形式にすると、手続き(procedure)、すなわち副作用だけを目的として実行されるメソッドのように見えるようになる。

これにならって、上のコードを書き換えてみる。

def forFiveTimes() { for (i <- 1 to 5) println("Hello World!") }

これでScalaっぽくできたんじゃないか!?やったね!Scalaでループ覚えたよ!

Conclusion

あとはwhile使ってみたり、再帰関数にしてみたのをGitHubに上げてみた。出力内容を何かしらのコレクションクラスに入れてからprintlnする、というのありかもしれない。

次のレッスンはFizzBuzzとかいう問題だ。ずいぶん強そうな名前だな。