複数のパラメーターリスト、たとえばdef foo(a:Int)(b:Int) = {}
およびリストごとの複数のパラメーター。 def foo(a:Int, b:Int) = {}
は、私の知る限り意味的に同等であり、ほとんどの関数型言語は、複数のパラメーターを宣言する1つの方法しか持っていません。 F#。
これらの両方のスタイルの関数定義をサポートする理由は、1つのパラメーターのみを含むパラメーターリストを使用して、構文のような言語拡張を許可するためです。
def withBufferedWriter(file: File)(block: BufferedWriter => Unit)
構文のように見えるようになりました
withBufferedWriter(new File("myfile.txt")) { out =>
out write "whatever"
...
}
ただし、複数のパラメーターリストを持たずに中かっこの使用をサポートする他の方法があります。
関連する質問:なぜScala "currying"と呼ばれる複数のパラメーターリストを使用するのですか?カリー化は、通常、部分適用をサポートするためにn項関数を単項にするための手法として定義されますただし、Scalaでは、関数の「カリー化」(各パラメーターが1つの複数のパラメーターリスト)バージョンを作成せずに、関数を部分的に適用できます。
次のことができるようになります:
scala> def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum
foo: (as: Int*)(bs: Int*)(cs: Int*)Int
scala> foo(1, 2, 3)(4, 5, 6, 7, 9)(10, 11)
res7: Int = 3906
言語の一部のように見えるメソッド(すでに見つけたもの)を作成できるようにするだけでなく、型推論器が一度に1つのブロックで機能することに注意してください。
これで:
def foo[T](a: T, b: T)(op: (T,T)=>T) = op(a,b)
foo(1,2){_+_}
T
は最初にInt
として推論され、クロージャー内の2つのアンダースコアの型として使用されます。これにより、コンパイラは、完全な型安全性を備えた+演算が有効であることを認識します。
「関連する質問」に答えるために、カリー化は、複数の引数の関数、たとえば_(A, B, C) => D
_を、1つの引数を取り関数を返す関数に変換する方法です。 A => (B => (C => D))
(括弧は表示されていますが、必須ではありません)。
タプル化された形式とカリー化された形式は同型であり、それらの間で自由に翻訳できます。これらはすべて同等ですが、構文上の意味が異なります。
_(A, B, C, D, E) => F
((A, B), (C, D, E)) => F
(A, B) => (C, D, E) => F
_
個別のパラメーターグループを宣言するとき、これは実行している種類のカレーです。 multi-parameter-groupメソッドは関数を返すメソッドです...これはREPLで見ることができます:
_scala> def foo(a:Int, b:Int)(c:Int, d:Int, e:Int):Int = 9
foo: (a: Int,b: Int)(c: Int,d: Int,e: Int)Int
scala> foo _
res4: (Int, Int) => (Int, Int, Int) => Int = <function2>
_
デフォルト引数の後方参照:
case class Foo(bar: Int)
def test(f: Foo)(i: Int = f.bar) = i*i
test(Foo(3))()
動機の1つが暗黙的なパラメーターリストだったことを知っています。 「暗黙的」はリストのプロパティであり、パラメータではありません。もう1つはおそらくケースクラスでした。最初のパラメーターリストのみがケースフィールドになります。