我之前问了这个问题:Combine a PartialFunction with a regular function
然后意识到,我实际上并没有问过它。 所以,这是另一种尝试。
如果我这样做:
val foo = PartialFunction[Int, String] { case 1 => "foo" }
val bar = foo orElse { case x => x.toString }
它无法编译:{{1}}
但这很好用:
error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: PartialFunction[?,?]
问题是有什么区别?在两种情况下,参数的类型都相同: val x: Seq[String] = List(1,2,3).collect { case x => x.toString }
。传入的值实际上是相同的。为什么一个案件有效,而另一个案件无效?
答案 0 :(得分:0)
您需要指定bar
的类型,因为编译器无法推断它。这编译:
val foo = PartialFunction[Int, String] { case 1 => "foo" }
val bar : (Int => String) = foo orElse { case x => x.toString }
答案 1 :(得分:0)
在List(1,2,3).collect{case x => x.toString}
的情况下,编译器能够根据List
的输入方式推断出部分函数的输入类型。
final override def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[List[A], B, That])
根据类型参数,编译器可以推断出您正在传递正确类型的部分函数。这就是List(1,2,3).collect{case x:String => x.toString}
无法编译,List(1,2,3).collect{case x:Int => x.toString; case x: String => x.toString}
的原因。
由于List
是协变的,编译器能够推断出部分函数{case x => x.toString}
是Int
上的部分函数。您会注意到List(1,2,3).collect{case x => x.length}
无法编译,因为编译器推断您正在Int
或Int
的子类上运行。
另请注意,{case x => x.toString}
只是语法糖。如果我们执行类似下面的操作,那么您的示例将按预期工作
val f = new PartialFunction[Int, String](){
override def isDefinedAt(x: Int): Boolean = true
override def apply(v1: Int): String = v1.toString
}
val foo = PartialFunction[Int, String] { case 1 => "foo" }
val bar = foo orElse f //This compiles fine.
List(1,2,3).collect{f} // This works as well.
因此,从我的观点来看,唯一合乎逻辑的答案是,能够为PartialFunction
生成{case x => x.toString}
实例的语法糖在编译时没有足够的信息才能将其充分输入为PartialFunction[Int, String]
案例中的orElse
。
答案 2 :(得分:0)
您可以使用库Extractor.scala。
import com.thoughtworks.Extractor._
// Define a PartialFunction
val pf: PartialFunction[Int, String] = {
case 1 => "matched by PartialFunction"
}
// Define an optional function
val f: Int => Option[String] = { i =>
if (i == 2) {
Some("matched by optional function")
} else {
None
}
}
// Convert an optional function to a PartialFunction
val pf2: PartialFunction[Int, String] = f.unlift
util.Random.nextInt(4) match {
case pf.extract(m) => // Convert a PartialFunction to a pattern
println(m)
case f.extract(m) => // Convert an optional function to a pattern
println(m)
case pf2.extract(m) => // Convert a PartialFunction to a pattern
throw new AssertionError("This case should never occur because it has the same condition as `f.extract`.")
case _ =>
println("Not matched")
}