26

Scala 様

scala> val f1: ((Int, Int)) => Int = { case (a, b) => a + b }
f1: ((Int, Int)) => Int = <function1>

scala> val f2: (Int, Int) => Int = { case (a, b) => a + b }
f2: (Int, Int) => Int = <function2>

は?!

scala> f1(1, 2)
res2: Int = 3

Ok...

scala> def takesIntInt2Int(fun: (Int, Int) => Int) = fun(100, 200)
takesIntInt2Int: (fun: (Int, Int) => Int)Int

scala> def takesTuple2Int(fun: ((Int, Int)) => Int) = fun(100, 200)
takesTuple2Int: (fun: ((Int, Int)) => Int)Int

scala> takesIntInt2Int(f2)
res4: Int = 300

scala> takesIntInt2Int(f1)
<console>:10: error: type mismatch;
 found   : ((Int, Int)) => Int
 required: (Int, Int) => Int
              takesIntInt2Int(f1)
                              ^

scala> takesTuple2Int(f1)
res6: Int = 300

scala> takesTuple2Int(f2)
<console>:10: error: type mismatch;
 found   : (Int, Int) => Int
 required: ((Int, Int)) => Int
              takesTuple2Int(f2)

右。そして今、これを見てください!

scala> takesTuple2Int { case (a, b, c) => a + b + c }
<console>:9: error: constructor cannot be instantiated to expected type;
 found   : (T1, T2, T3)
 required: (Int, Int)
              takesTuple2Int { case (a, b, c) => a + b + c }
                                    ^

scala> takesIntInt2Int { case (a, b, c) => a + b + c }
<console>:9: error: constructor cannot be instantiated to expected type;
 found   : (T1, T2, T3)
 required: (Int, Int)
              takesIntInt2Int { case (a, b, c) => a + b + c }

のように、srsly ? o_O どちらもrequired: (Int, Int)エラーになります。

それでは、なぜそのcaseような無名関数でまったく使用するのでしょうか?

4

1 に答える 1

18

Scala リファレンス ( http://www.scala-lang.org/files/archive/nightly/pdfs/ScalaReference.pdf ) のセクション 8.5 を参照してください。式{ case (a, b) => a + b }は、予想される型に基づいて異なる方法で解釈されます。あなたの定義では、 aにキャストさf1れた a を作成しました。つまり、それの定義ではa を作成しました。PartialFunction[(Int, Int), Int]Function1[(Int, Int), Int]((Int, Int)) => Intf2Function2[Int, Int, Int](Int, Int) => Int

これらの 2 つの解釈は、無名関数で一般的にケースを使用する 2 つの状況に関連しています。

1 つは、 で行ったように、タプルを受け入れてそのコンポーネントで動作する無名関数を作成するためのものですf1。例として、 の or メソッドに渡す関数がforeachありmapます。MapMap(1 -> 2, 3 -> 4) map { case (k, v) => k + v }

match2 つ目は、唯一のパラメーターでa を実行する無名関数を作成するためのものです。あなたf2はこれを行っていますが、有用な方法ではありません。例としては、 に渡される無名関数がありcollectますList(1, -2, 3) collect { case x if x > 0 => -x }

2 つを組み合わせることができることに注意してください。つまり、関数 likef1は複雑なマッチングも行うことができます。たとえば、Map(1 -> 2, 3 -> 4) collect { case (k, v) if k < 2 => v }.

編集:res2タプリングのために機能します。アプリケーションが型チェックを行わない場合、コンパイラは失敗する前に引数をタプルにラップしようとします。

しかし、それはアプリケーションのためだけに試みられています。あなたが発見したように、それは一般的な変換ではありません。Function2[A, B, C]値をにアップグレードしようとはしませんFunction1[(A, B), C]

于 2013-10-20T14:46:14.457 に答える