Scalaの関数と閉パッケージ

2791 ワード

関数(Functions)
関数はScalaにおいてメソッド(methods)の他にも多様な形態が存在し,局所関数(local functions),関数数値面量(function literals),関数値(function values)である.
方法
最も一般的なのは、オブジェクトのメンバーとして関数を定義することです.このような関数は と呼ばれます.
ローカル関数(Local Functions)
関数にローカル変数を定義するように、主に関数命名汚染(pollute)の問題を解決するためにローカル関数を定義できます.また、いくつかのツール関数に柔軟性(flexiblity)の保証を持たせることもできます.
ファーストクラス関数(First-Class Functions)
関数はScalaではトップクラスの関数です.つまり、関数を定義して呼び出すだけでなく、名前の付いていない関数の字面量を書いて値として参照することもできます.
1つの関数数値面量はクラス(class)にコンパイルされ、実行時に関数値にインスタンス化される.したがって,関数値と関数値の違いは,関数値がソースコードに存在し,関数値がオブジェクト(object)として実行時に存在することである.クラス(source code)とオブジェクト(object)の関係に類比できる=>の理解については、高等数学における関数に関するマッピング関係を類比することができる.この記号はこの関数が左の式を右の式に変換することを示しています.
函数面量の略語(呼び出し中のみ)
1.型推定により、型パラメータ2を省略することができる.パラメータが1つしかない場合は、カッコ3を省略することができる.各パラメータが関数の数の面量に1回しか現れない場合は、プレースホルダ構文(Placeholder Syntax)を使用します.
部分応用関数(Partially Applied Functions)
Scalaでは、関数を呼び出し、必要なすべてのパラメータを渡すと、これらのパラメータにこの関数を適用します.一部の適用関数は、この関数に必要なすべてのパラメータを提供する必要はありません.一部のパラメータを提供します.
関数の後ろに下線プレースホルダ(スペース付き)を配置すると、単一のパラメータ(single parameter)ではなく、パラメータリスト全体(entire parameter list)を表すプレースホルダが配置されます(もちろん、一部のパラメータには次の世代を割り当てることもできます).これにより、関数の一部が適用されます.
この下線(underscope)は、defの関数を関数値(function value)に変換することである.
応用関数の一部を一言でまとめることができます.1つの関数を一部のパラメータに適用し、コンパイラは関数数値の面量を生成し、実行時に関数数値の面量の関数値オブジェクトをインスタンス化し、残りのパラメータをこの関数値オブジェクトに渡すと、元の関数を呼び出す関数値オブジェクトのapplyメソッドが呼び出されます.
クローズド・パッケージ
閉包という言葉は にバインドされた自由変数(free variables)から 関数の数値面量に由来する.ここでの自由変数とは,関数数値面量がコンテキストでその変数の正確な意味を与えることができないことを意味し,逆に正確な意味を与えることができる変数をバインド変数(bound variables)と呼ぶ.
任意の関数数値面量には自由変数が含まれていません. (closed term)と呼ばれます.任意の関数数値面量には自由変数が含まれています. (open term)と呼ばれます.つまり、閉パケットは最終的に自由変数のキャプチャによって開項生成関数値を閉じます.
Scalaの閉パケットは、 自由変数そのものであり、この変数が指す値ではない.すなわち,閉パケット外は閉パケットによる自由変数の修正を感知でき,外部自由変数の変化は閉パケット内部でも感知できる.
特殊なメソッド呼び出し
反復パラメータ(Repeated Parameters)
パラメータリストの最後のパラメータが繰り返し可能であることを指定できます.関数の内部には、重複パラメータが配列として存在します.
def echo(foo: Int, bar: Int, others: String*) = {
    // ...
}

同じタイプの配列を繰り返しパラメータに渡すには、次のようにします.
val arr = Array("hello", "world")
echo(1, 2, arr: _*)

名前付きパラメータ(Named arguments)
名前付きパラメータを使用すると、次のようなパラメータを異なる順序で渡すことができます.
def func(foo: Int, bar: Int) = { /* ... */ }
func(1, 2)
func(bar = 2, foo = 1) // named arguments invoked.

デフォルトパラメータ値(Default parameter values)
デフォルトパラメータ値は一般的に名前付きパラメータと組み合わせて使用され、パラメータにデフォルト値がある場合は、 パラメータの転送を選択できます.
末尾再帰(tail recursive)
再帰関数は、最後の行で自身を呼び出すと、Scalaは を採用し、コンパイラはこの関数をwhile loopで書き換えます.
テール再帰には多くの利点があり、呼び出しスタックフレームを低減し、スタックオーバーフローエラーを防止し、メモリ使用を低減し、性能上の最適化をもたらす.