関数は Function トレイトである

第一級関数

Scala において、関数は第一級関数 first-class function です。第一級関数なので、関数を値の様にして扱うことができます。例えば以下のように関数を f という値として定義できます。

val f:Int=>Int = x=>x*x
println(f(3))

結果は 9 が出力されます。


上記は以下と同じ意味になります。

val f:Function[Int, Int] = x=>x*x
println(f.apply(3))

f(3) の呼び出しは実際には Function 型の apply メソッドの呼び出しでしかないのです。


さらに以下に書き換えることができます。

val f:Function[Int, Int] = new Function[Int, Int]{
  def apply(x:Int):Int = x*x
}
println(f.apply(3))

Function の無名クラス定義にて apply メソッドを定義しています。


さらに冗長に書いてみると以下とも同じ意味です。

class Square extends Function[Int,Int] {
  def apply(x:Int):Int = x*x
}

val f:Function[Int, Int] = new Square
println(f.apply(3))

ということで、関数は Function のインスタンスの apply メソッドを定義しているというわけです。

Scalaのライブラリの中を見ると

Function[Int, Int] が何を意味するかというと、Predef にて以下の定義となっています。

type Function[-A, +B] = Function1[A, B]

Function は Function1 の型エイリアスとなっています。

そして、Function1 は、

trait Function1[-T1, +R] extends AnyRef { self =>
  def apply(v1:T1): R
  ・・・

のような trait となっています。T1 を引数にとり、R を結果型として返す apply 関数が定義されていますね。

つまり、

Int=>Int

Function1[Int, Int]

は同じ意味となります。

また、

x=>x*x

def apply(x:Int):Int = x*x

のメソッドを定義していることになります。