2017-11-10 3 views
1

部分的にvarargsでカリー化された関数を適用するのに奇妙なことがあります。この例を考えてみましょう:部分的に適用された関数をvarargsで定義して呼び出しますか?

def adder(a: Int)(b: Int*) = b.map(_ + a) 

adder(1)(1,2,3,4)  // res1: Seq[Int] = ArrayBuffer(2, 3, 4, 5) 
val add2 = adder(2) _ // add2: Seq[Int] => Seq[Int] 
add2(1,2,3,4)   // Fails to compile 
add2(Seq(1,2,3,4)  // res3: Seq[Int] = List(3, 4, 5, 6) 

私はprevious questionを認識していますが、私はまだ、コンパイラがこれを行う理由は、これらのケースでいくつかの巧妙な解決策があるかどうかを知りたいです。

答えて

2

これは、メソッドと関数がScalaでは異なるためです。メソッドを使用すると、ETAの拡張method _を行うと、メソッドは単にFunction0Function22への形質のインスタンスである関数に変換され

などの型パラメータ、デフォルトおよび名前付き引数、可変引数、暗黙の引数リストを、サポート、およびdoesnのこれらの機能のいずれかをサポートしていません。

簡略化してInt => Stringまたは(A, B) => Rという関数タイプを表すことができます。一方、メソッドにはnon-value typesがあり、Scalaプログラムでそのような型を参照する一般的な方法はありません。

あなたは可変引数をサポートしている呼び出し可能な変数、または任意の他の方法の機能を持つようにしたい場合は、適切なapplyメソッドを持つオブジェクトを返すことができます。

case class adder(a: Int) { 
    def apply(b: Int*) = b.map(_ + a) 
} 

今では動作します:

scala> adder(1)(1,2,3,4) 
res1: Seq[Int] = ArrayBuffer(2, 3, 4, 5) 

scala> val add2 = adder(2) 
add2: adder = adder(2) 

scala> add2(1,2,3,4) 
res2: Seq[Int] = ArrayBuffer(3, 4, 5, 6) 
関連する問題