¿Hay una manera más agradable de levantar una función parcial en Scala?
-
12-10-2019 - |
Pregunta
I de vez en cuando venir a través del siguiente patrón, en el que esencialmente tienen un PartialFunction[SomeType,AnotherType]
, y quiero tratarlo como un Function[SomeType,Option[AnotherType]
, por ejemplo:
def f(s:SomeType):Option[AnotherType] = s match {
case s1:SubType1 => Some(AnotherType(s1.whatever))
case s2:SubType2 => Some(AnotherType(s2.whatever))
case _ => None
}
¿Hay una manera de escribir la función anterior de una manera que evita el caso por defecto y envolviendo el resultado en Some
donde se define? El mejor que he encontrado hasta el momento es la siguiente:
def f(s:SomeType):Option[AnotherType] = pf.lift(s)
def pf:PartialFunction[SomeType,AnotherType] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}
¿Hay una manera de hacerlo sin definir una función intermedia? Ya lo he intentado varias cosas en la línea de lo siguiente, pero no tengo nada para compilar aún:
def f:Function[SomeType,Option[AnotherType]] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}.lift
Solución
condOpt
en scala.PartialFunction objeto. Desde el scaladoc:
def onlyInt(v: Any): Option[Int] = condOpt(v) { case x: Int => x }
Otros consejos
No tanto una respuesta, como una explicación de por qué la respuesta es correcta huynhjl de ...
Parte de su confusión es que usted está tratando de def
una función parcial. Todo esto hace es crear un método que devuelve un objeto PartialFunction
, cuando usted puede también crear la cosa directamente:
val pf: PartialFunction[SomeType,AnotherType] = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
}
A pesar de que personalmente prefiero tipo de uso de adscripción:
val pf = {
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]
De cualquier manera, hay que especificar qué tipo de entrada es, por lo que tiene que dar la firma exacta de la PartialFunction
. Sé que se siente como que debería ser posible inferir esto, pero, por desgracia, eso no es tristemente el caso!
El uso de la versión atribuida, a continuación, puede definir y levantar todos en el mismo lugar:
val pf = ({
case s1:SubType1 => AnotherType(s1.whatever)
case s2:SubType2 => AnotherType(s2.whatever)
} : PartialFunction[SomeType,AnotherType]).lift
PartialFunction.condOpt
es la mejor solución, sin embargo, ya que permite al inferencer hacer la mayor parte de este trabajo para usted, dejando mucho código más limpio:)