公式のScalaチュートリアルをやってみる(1)

やってみる。

[scala]
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
[/scala]

実行する。Hello, World!と表示される。どうも。行末のセミコロンは省略できる。

[scala]
import java.util.{Date, Locale}
import java.text.DateFormat
import java.text.DateFormat._

object FrenchDate {
def main(args: Array[String]) {
val now = new Date
val df = getDateInstance(LONG, Locale.FRANCE)
println(df format now)
}
}
[/scala]

すると、 今日の日付、5 octobre 2014と表示される。オクトブレーなんだね。フランス語だと。

Javaのクラスは全部使えるらしい。{}で囲ってるのはDateとLocale二つをimportしますよ、ということですね。2行書かなくていいという事ですね。_はjavaで言う*と等価だそうです。なぜ*を使わないかというと、Scalaでは*はメソッド名などに普通に使えるキーワードだからだそうで。

ここで特徴的なのは

df format now

の部分。これは、

df.format(now)

と等価らしい。なのでそう書いてみる。同じ結果が得られる。なるほど。Scalaの演算子はすべてメソッドとして扱われるらしい。なので、

println(1.+(2))

と書けば3と表示される。+という名前のメソッドとして加算が定義されているということですね。Scalaはピュアオブジェクト指向言語なので数値も何もかもオブジェクトでプリミティブ型というのは無いらしい。

また、関数もオブジェクトなので

[scala]
object Timer {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def timeFlies() {
println("time flies like an arrow...")
}

def main(args: Array[String]) {
oncePerSecond(timeFlies)
}

}
[/scala]

と言う風に書ける。実行すると文字が1秒おきに出る。まあ関数オブジェクトはむしろ最近の言語では一般的で、Java8以前がむしろ特殊だったと言えるのですんなり受け入れることはできますね。

ここでUnitというのが出てきましたが、これはつまりvoidと同じようなものだそうです。何も受け取らず、何も返さない関数を引数にとるということですね。

匿名関数は下記のように書けます。C#などと同じような形式の=>ですね。

[scala]
object TimerAnonymous {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def main(args: Array[String]) {
oncePerSecond(() =>
println("time flies like an arrow..."))
}
}
[/scala]

実行結果は同じです。

クラスは下記のような感じで宣言します。複素数の例ですね。

[scala]
class Complex(real: Double, imaginary: Double) {
def re() = real
def im() = imaginary
}
[/scala]

Scalaではコンストラクタが上記のように簡単に書けるそうです。これで、実数部realと虚数部imaginaryを引数にとり、実数部を返却するre()メソッドと虚数部を返却するim()メソッドができます。戻り値の型が書いていませんが、コンパイラが推論して決定します。この場合はDoubleが戻り値の型になります。推論できなければエラーになります。

[scala]
class Complex(real: Double, imaginary: Double) {
def re():Double = real
def im():Double = imaginary
}
[/scala]

上記のように書くのと変わらないということですね。

[scala]
object Main{
def main(args: Array[String]) {
val c1 = new Complex(1.0, 2.0)
println(c1.im())
}
}
[/scala]

と、書けば2.0と表示されます。

[scala]
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
}
[/scala]

ちなみに、引数がゼロのメソッドは上記のようにカッコを省略できるそうです。ここまでくるとちょっと混乱するね。普通の変数のようだ。

オーバーライドは、

[scala]
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
override def toString() =
"" + re + (if (im < 0) "-" else "+") + im + "i"
}
[/scala]

このようにする。

case class, trait, ジェネリクスはまた今度。