scala - "case"匿名函数如何在 Scala 中真正工作?

标签 scala pattern-matching

亲爱的斯卡拉,

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在这样的匿名函数中?

最佳答案

请参阅 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 .

这两种解释与您通常在匿名函数中使用 case 的两种情况有关。

一种用于编写接受元组并处理其组件的匿名函数,就像您对 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因为元组而起作用。如果应用程序不进行类型检查,编译器将在失败之前尝试将 args 包装在元组中。

但这只是针对应用程序进行的尝试;正如您所发现的,这不是一般的转换。它不会尝试升级值 Function2[A, B, C]Function1[(A, B), C] .

关于scala - "case"匿名函数如何在 Scala 中真正工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19478244/

相关文章:

json - Scala,喷雾-json : universal enumeration json formatting

generics - 我可以创建与实现模式的泛型类型的匹配吗?

haskell - 在haskell中foreach的初学者/学习者实现

java.lang.Object 无法转换为 boolean

java - 为什么我的环境变量在 Windows 系统的 common shell 中有效,但在 power shell 中无效?

scala - AnyRef.eq 方法的默认实现

java - 使用 Scala Trait 扩展 Java 类

opencv - 如何找到稍微拉长的椭圆形/带有弯角的矩形/有时是圆弧形的形状?

haskell - Lisp 中复制 Mathematica 功能的替换函数

c# - C# 中的模式匹配 F# 中定义的类型