関数型言語としてのScala
「今からでも遅くない これから始めるScala」の中編である今回は、Scalaの関数型言語としての側面を紹介します。
「関数型言語」と言ってもさまざまなものがあります。LispやScheme、Haskell、OCaml、Erlangなどですが、どれも「ファーストクラスの関数オブジェクトを持つ」という特徴があります。つまり関数を値として変数に代入したり、関数の引数に関数を与えたり、関数オブジェクトを新しく作り出す関数を定義したり、ということが可能です。
関数についてのおさらい
前編で解説した内容ですが、Scalaでの関数定義の方法をおさらいします。
関数の定義
Scalaでは、関数の宣言はdefキーワードを用います。次のような書式となります。
def 関数名[型パラメータ]( 引数名:引数型,・・・ ):結果型 = { 関数本体 }
以下は、偶数であるか判定する関数です。
scala> def isEven( n:Int ):Boolean = { | n % 2 == 0 | } isEven: (n: Int)Boolean scala> isEven( 4 ) res0: Boolean = true
Scalaでは、関数本体のなかで最後に評価された式の値が結果値となります。また、関数宣言の結果型は省略可能であり、本体が一つの式である場合は{}を省略できます。isEven関数を省略したものが以下の定義です。
scala> def isEven( n:Int ) = n % 2 == 0 isEven: (n: Int)Boolean scala> isEven( 4 ) res0: Boolean = true
関数リテラル・無名関数
Scalaではその場で名前をつけずに関数オブジェクトを作り出す関数リテラルという記法があります。
文字列は、val s = "foo"のようにダブルクォートで囲むことで生成できますので、わざわざnew String("foo")のように書くことはありません。これと同様に関数を生成する記法が関数リテラルです。
関数リテラルの書き方はいろいろなバリエーションがありますが、最もオーソドックスな記法は次のように書きます。
(引数1:型, 引数2:型, ・・・) => { 処理 }
先ほどのisEven関数を、関数リテラルを用いて定義してみます。
scala> val isEven = (n:Int) => n % 2 == 0 isEven: (Int) => Boolean = <function1> scala> isEven( 4 ) res0: Boolean = true
isEvenという変数に、関数リテラルを用いて生成した「(n:Int) => n % 2 == 0」という関数オブジェクトを代入しています。このように、変数に代入した関数オブジェクトも、通常の関数呼び出しのように「変数名(引数)」という書式で呼び出すことができます。
ここまでが、前回取り上げた関数に関してのおさらいです。