Dast 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
好的...
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
?
答案 0 :(得分:17)
请参阅Scala参考(http://www.scala-lang.org/files/archive/nightly/pdfs/ScalaReference.pdf)的第8.5节。表达式{ case (a, b) => a + b }
根据预期的类型进行不同的解释。在您对f1
的定义中,它创建了一个PartialFunction[(Int, Int), Int]
,其被转换为Function1[(Int, Int), Int]
,即((Int, Int)) => Int
,而在f2
的定义中,它创建了Function2[Int, Int, Int]
},即(Int, Int) => Int
。
这两种解释与通常在匿名函数中使用案例的两种情况有关。
一个用于编写接受元组并处理其组件的匿名函数,就像使用f1
一样。一个示例是您传递给foreach
上的map
或Map
方法的功能,例如Map(1 -> 2, 3 -> 4) map { case (k, v) => k + v }
。
第二个是编写一个匿名函数,它在其唯一参数上执行match
。您的f2
正在执行此操作,但没有任何有用的方式。一个例子是传递给collect
的匿名函数,例如List(1, -2, 3) collect { case x if x > 0 => -x }
。
请注意,两者可以组合,即像f1
这样的函数也可以进行复杂匹配。例如,Map(1 -> 2, 3 -> 4) collect { case (k, v) if k < 2 => v }
。
编辑:res2
因为元组而起作用。如果应用程序没有键入check,编译器将尝试在失败之前将args包装在元组中。
但这只是针对应用程序而尝试的;你发现它并不是一般的转换。它不会尝试将值Function2[A, B, C]
升级为Function1[(A, B), C]
。