関数

型パラメータの変位指定とか境界とかを読んでいたんだけど、いまいちよくわからないので、とりあえずパスして関数に行く。

関数

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 が返り値の型。こっちのほうが多用されるので覚えておくこと。