Frage

In Scala, die PartialFunction[A, B] Klasse von Typ Function[A, B] abgeleitet ist (siehe Scala Reference, 12.3.3). Dies scheint jedoch nicht eingängig zu mir, da ein Function (die für alle A definiert werden muss) strengere Anforderungen als ein PartialFunction hat, die an einigen Stellen nicht definiert werden kann.

Das Problem kam ich habe accross war, dass, wenn ich eine Teilfunktion haben, kann ich nicht eine Function verwenden, um die Teilfunktion zu verlängern. Z.B. Ich kann es nicht tun:

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

(Hoffnung die Syntax ist mindestens fern rechts)

Warum ist diese Subtyping umgekehrt getan? Gibt es Gründe, die ich übersehen habe, wie die Tatsache, dass die Function Typen eingebaut sind?

BTW, wäre es auch schön, wenn Function1 :> Function0 so brauche ich nicht das Dummy-Argument in dem obigen Beispiel habe: -)

Bearbeiten, um das Problem zu klären Subtyping

Der Unterschied zwischen den beiden Ansätzen kann durch einen Blick auf zwei Beispiele hervorgehoben werden. Welche von ihnen ist richtig?

One:

val zeroOne : PartialFunction[Float, Float] = { case 0 => 1 }
val sinc = zeroOne orElse ((x) => sin(x)/x) // should this be a breach of promise?

Zwei:

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?

Keine korrekte Lösung

Andere Tipps

Da in Scala (wie in jedem Turing komplette Sprache) gibt es keine Garantie dafür gibt, dass eine Funktion insgesamt ist.

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

Diese Funktion ist nicht definiert auf 0 A Partielle Funktion ist nur eine Funktion, die Ihnen zu sagen, verspricht, wo es nicht definiert ist. Dennoch Scala macht einfach genug, um es zu tun, was Sie wollen

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

Wenn Sie möchten, können Sie func2Partial implizit machen.

PartialFunction hat Methoden, die Function1 nicht der Fall, daher der Subtyp ist. Diese Methoden sind isDefinedAt und orElse.

Ihr Problem ist, dass PartialFunctions manchmal nicht geschlossen, wenn Sie wirklich wie sie würden sein. Ich bin zuversichtlich, dass zu einem späteren Zeitpunkt behandelt werden. Zum Beispiel funktioniert das nicht:

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" })

Aber das tut:

scala> pf orElse ({ case x => "default" } : PartialFunction[String,String])
res5: PartialFunction[String,String] = <function>

Natürlich könnte man dies immer tun:

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]

Und es ist jetzt mehr wie Sie wollen:

scala> pf orElse ((x: String) => "default")
res7: PartialFunction[String,String] = <function>

scala> println(res7("a") + " " + res7("quux"))
foo default
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top