48

在 Scala 中,PartialFunction[A, B]类派生自类型Function[A, B](参见 Scala 参考,12.3.3)。但是,这对我来说似乎违反直觉,因为 a Function(需要为 all 定义A)比 a 具有更严格的要求PartialFunction,在某些地方可能未定义。

我遇到的问题是,当我有一个偏函数时,我不能使用 aFunction来扩展偏函数。例如。我不能做:

(pf orElse (_)=>"default")(x)

(希望语法至少远程正确)

为什么这个子类型是反向进行的?有没有我忽略的原因,比如Function类型是内置的?

顺便说一句,如果Function1 :> Function0我不需要上面示例中的虚拟参数,那也很好:-)

编辑以澄清子类型问题

通过查看两个示例可以强调两种方法之间的区别。他们哪一个是对的?

一:

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?
4

2 回答 2

34

因为在 Scala 中(就像在任何图灵完备语言中一样),不能保证函数是完全的。

val f = {x : Int => 1 / x}

该函数未在 0 处定义。PartialFunction 只是一个承诺告诉您未定义的函数。尽管如此,Scala 仍然可以轻松地做你想做的事

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 设为隐式。

于 2009-05-30T23:22:08.593 回答
18

PartialFunctionFunction1没有的方法,因此它是子类型。这些方法是isDefinedAtorElse

您真正的问题是,PartialFunction当您真正希望它们时,有时不会推断出 s 。我希望这将在未来的某个日期得到解决。例如这不起作用:

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
于 2009-06-03T16:37:15.217 回答