为什么Scala中的PartialFunction <:Function?
在Scala中, PartialFunction[A, B]
类是从Function[A, B]
types派生的(参见Scala参考,12.3.3)。 但是,这对我来说似乎是违反直觉的,因为一个Function
(需要为所有A
定义)比PartialFunction
有更严格的要求,在某些地方可能是未定义的。
我遇到的问题是,当我有一个部分函数,我不能使用Function
来扩展部分函数。 例如。 我不能做:
(pf orElse (_)=>"default")(x)
(希望语法至less是远程的权利)
为什么这个子types是相反的? 是否有任何我忽略的原因,比如Function
types是内置的?
顺便说一句,如果Function1 :> Function0
,这也不错,所以我不需要在上面的例子中有伪参数:-)
编辑澄清子types问题
两种方法的区别可以通过两个例子来强调。 哪一个是对的?
一:
val zeroOne : PartialFunction[Float, Float] = { case 0 => 1 } val sinc = zeroOne orElse ((x) => sin(x)/x) // should this be a breach of promise?
二:
def foo(f : (Int)=>Int) { print(f(1)) } val bar = new PartialFunction[Int, Int] { def apply(x : Int) = x/2 def isDefinedAt(x : Int) = x%2 == 0 } foo(bar) // should this be a breach of promise?
因为在Scala中(就像在任何图灵语言中一样),不能保证函数是完整的。
val f = {x : Int => 1 / x}
该函数没有被定义为0. PartialFunction只是一个函数,可以告诉你它没有被定义在哪里。 不过,斯卡拉可以很容易地做你想做的事情
def func2Partial[A,R](f : A => R) : PartialFunction[A,R] = {case x => f(x)} val pf : PartialFunction[Int, String] = {case 1 => "one"} val g = pf orElse func2Partial{_ : Int => "default"} scala> g(1) res0: String = one scala> g(2) res1: String = default
如果你愿意,你可以使func2Partial隐式。
PartialFunction
有Function1
没有的方法,因此它是子types。 这些方法是isDefinedAt
和orElse
。
你真正的问题是,当你真的喜欢他们的时候, PartialFunction
不是被推断出来的。 我希望这将在未来的某个时候解决。 例如这不起作用:
scala> val pf: PartialFunction[String, String] = { case "a" => "foo" } pf: PartialFunction[String,String] = <function> scala> pf orElse { case x => "default" } <console>:6: error: missing parameter type for expanded function ((x0$1) => x0$1 match { case (x @ _) => "default" })
但是这样做:
scala> pf orElse ({ case x => "default" } : PartialFunction[String,String]) res5: PartialFunction[String,String] = <function>
当然你可以这样做:
scala> implicit def f2pf[T,R](f: Function1[T,R]): PartialFunction[T,R] = new PartialFunction[T,R] { def apply(x: T) = f(x) def isDefinedAt(x: T) = true } f2pf: [T,R](f: (T) => R)PartialFunction[T,R]
现在更像你想要的:
scala> pf orElse ((x: String) => "default") res7: PartialFunction[String,String] = <function> scala> println(res7("a") + " " + res7("quux")) foo default