Pregunta

En Scala, la clase PartialFunction[A, B] se deriva de tipo Function[A, B] (ver Scala Reference, 12.3.3). Sin embargo, esto parece contrario a la intuición para mí, ya que un Function (que debe ser definido para todos A) tiene requisitos más estrictos que un PartialFunction, que puede ser indefinido en algunos lugares.

El problema que he encontré con que era cuando tengo una función parcial, no puedo utilizar un Function para ampliar la función parcial. P.ej. No puedo hacer:

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

(Hope la sintaxis es al menos de forma remota derecha)

¿Por qué se hace en sentido inverso subtipos? ¿Hay algunas razones por las que he pasado por alto, al igual que el hecho de que los tipos Function están incorporados?

Por cierto, sería bueno si también Function1 :> Function0 por lo que no necesita tener el argumento ficticio en el ejemplo anterior: -)

Editar para aclarar el problema de subtipos

La diferencia entre los dos enfoques se pueden valorizar con dos ejemplos. ¿Cuál de ellas es la correcta?

Uno:

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

Dos:

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?

No hay solución correcta

Otros consejos

Debido a que en Scala (como en cualquier lenguaje Turing completo) no hay garantía de que una función es total.

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

Esta función no está definida en 0. Una función parcial es sólo una función que promete decir que donde no está definido. Aún así, Scala hace que sea bastante fácil de hacer lo que quiera

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

Si lo prefiere, puede hacer func2Partial implícita.

PartialFunction tiene métodos que Function1 no, por lo tanto, es el subtipo. Esos métodos son isDefinedAt y orElse.

Su verdadero problema es que PartialFunctions no se infieren a veces, cuando realmente te gustaría que fueran. Tengo la esperanza de que será tratado en una fecha futura. Por ejemplo esto no funciona:

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

Sin embargo, esto hace:

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

Por supuesto, siempre se puede hacer esto:

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]

Y ahora es más como desea:

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

scala> println(res7("a") + " " + res7("quux"))
foo default
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top