Scala Language
関数
サーチ…
備考
Scalaにはファーストクラスの機能があります。
関数とメソッドの違い:
関数はScalaのメソッドではありません。関数は値であり、そのように割り当てられます。一方、 def
( def
を使用して作成された)メソッドは、クラス、特性、またはオブジェクトに属していなければなりません。
- 関数は、コンパイル時に特性(
Function1
など)を拡張するクラスにコンパイルされ、実行時に値にインスタンス化されます。一方、メソッドは、そのクラス、特性、またはオブジェクトのメンバーであり、その外には存在しません。 - メソッドを関数に変換することはできますが、関数をメソッドに変換することはできません。
- メソッドは型パラメータ化を持つことができますが、関数は型パラメータ化できません。
- メソッドはパラメータのデフォルト値を持つことができますが、関数はできません。
匿名関数
匿名関数は、定義されていて名前を割り当てられていない関数です。
以下は、2つの整数を取り、その合計を返す無名関数です。
(x: Int, y: Int) => x + y
結果の式をval
代入することができます。
val sum = (x: Int, y: Int) => x + y
匿名関数は、主に他の関数の引数として使用されます。たとえば、コレクションのmap
関数は、引数として別の関数を期待しています。
// Returns Seq("FOO", "BAR", "QUX")
Seq("Foo", "Bar", "Qux").map((x: String) => x.toUpperCase)
無名関数の引数の型は省略できます:型は自動的に推論されます :
Seq("Foo", "Bar", "Qux").map((x) => x.toUpperCase)
引数が1つだけの場合、その引数の前後のカッコは省略できます。
Seq("Foo", "Bar", "Qux").map(x => x.toUpperCase)
下線は略語
引数の名前を必要としない、さらに短い構文があります。上記のスニペットは次のように記述できます:
Seq("Foo", "Bar", "Qux").map(_.toUpperCase)
_
は無名関数の引数を位置的に表します。複数のパラメータを持つ無名関数では、 _
が出現するたびに異なる引数が参照されます。たとえば、次の2つの式は等価です。
// Returns "FooBarQux" in both cases
Seq("Foo", "Bar", "Qux").reduce((s1, s2) => s1 + s2)
Seq("Foo", "Bar", "Qux").reduce(_ + _)
この短縮形を使用する場合、位置_
によって表される引数は、1回だけ同じ順序で参照することができます。
パラメータなしの無名関数
パラメータを使用しない無名関数の値を作成するには、パラメータリストを空白のままにします。
val sayHello = () => println("hello")
組成
機能構成は、2つの機能を動作させ、単一の機能として見ることができる。関数f(x)
と関数g(x)
与えられたg(x)
、関数h(x) = f(g(x))
と数学的に表現される。
関数がコンパイルされると、 Function1
関連する型にコンパイルされます。 Scalaは、composition: andThen
とcompose
関連するFunction1
実装の2つのメソッドを提供します。 compose
メソッドは、上記の数学的定義に適合します。
val f: B => C = ...
val g: A => B = ...
val h: A => C = f compose g
andThen
( h(x) = g(f(x))
)は、より「DSLのような」感情を持っています:
val f: A => B = ...
val g: B => C = ...
val h: A => C = f andThen g
新しい無名関数が割り当てられ、 f
とg
閉じられます。この関数は、両方の場合に新しい関数h
に束縛されます。
def andThen(g: B => C): A => C = new (A => C){
def apply(x: A) = g(self(x))
}
f
またはg
いずれかが副作用で動作する場合、 h
を呼び出すと、 f
とg
すべての副作用がその順序で発生します。変更可能な状態の変更についても同様です。
部分関数との関係
trait PartialFunction[-A, +B] extends (A => B)
すべての単一引数PartialFunction
もFunction1
です。これは正式な数学的意味では直感的ではありませんが、オブジェクト指向の設計に適しています。このため、 Function1
は、常にtrue
isDefinedAt
メソッドを提供する必要はありません。
部分関数(関数でもある)を定義するには、次の構文を使用します。
{ case i: Int => i + 1 } // or equivalently { case i: Int ⇒ i + 1 }
詳細については、 PartialFunctionsを見てください 。