型パラメータの変位指定とか境界とかを読んでいたんだけど、いまいちよくわからないので、とりあえずパスして関数に行く。
関数
Scala の関数は、ほかの言語とはちょっと趣が違う。関数は単に Function0 から Function22 までのトレイトのサブクラスのインスタンスなのだそうだ。0 とか 22 とかの数字は引数の数らしい。例えば、2つの整数を足し算する関数 add は次のように定義する。
scala> val add = new Function2[Int, Int, Int] { | def apply(x: Int, y: Int): Int = x + y | } add: (Int, Int) => Int = <function2>
ああ、ここでもよくわからないぞ。トレイトは直接インスタンス化できないんじゃなかったのか?それと new キーワードでインスタンスを作るときにメソッドの定義もできるの?いつそんな話があった?
まぁいい。そういうものだと思っておこう。Function2 というのは引数を2つとる関数(の元)だけど、型パラメータが3つあるのは最後の1つは返り値の型のようだ。こういうふうに使う。
scala> add.apply(200, 300) res0: Int = 500
または、apply メソッドは特別扱いされるので次のようにも書ける。こっちのほうが関数らしい。
scala> add(200, 300) res1: Int = 500
無名関数
注意する点として、厳密には add というのは変数の名前であって、そこに代入されている関数オブジェクトの名前ではない、ということがある。つまりこれは無名関数なわけだ。そして無名関数らしくかけるように、シンタックスシュガーが用意されている。
scala> val add2 = (x: Int, y: Int) => x + y add2: (Int, Int) => Int = $$Lambda$3280/2126394127@24301165
うーん、冒頭の new Function2 を使って定義したときと、REPL のレスポンスが違うな。そういうものなんだろうか。何か違うのか?
まぁいいや。とりあえずこれも無名関数が変数 add2 に代入されているってことのようだ。で、次のように使える。
scala> add2(1, 3) res2: Int = 4
関数の型
上のように定義した関数の型は、本来 FunctionN[…] のように表記すべきところ、これまたシンタックスシュガーが用意されている。次のようになる。
(N1, N2, ..., NN) => B
N1 から NN までが引数の型で、B が返り値の型。こっちのほうが多用されるので覚えておくこと。