Question

J'ai deux PartialFunctions f et g.Ils n’ont aucun effet secondaire et sont rapides à exécuter.Quelle est la meilleure façon de les composer dans une autre fonction partielle h tel queh.isDefinedAt(x) si et si f.isDefinedAt(x) && g.isDefinedAt(f(x))?

C'est également OK si h est une fonction renvoyant un Option plutôt qu'une fonction partielle.

je suis déçu que f andThen g ne fait pas ce que je veux :

scala> val f = Map("a"->1, "b"->2)
f: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)

scala> val g = Map(1->'c', 3->'d')
g: scala.collection.immutable.Map[Int,Char] = Map(1 -> c, 3 -> d)

scala> (f andThen g).isDefinedAt("b")
res3: Boolean = true

scala> (f andThen g).lift("b")
java.util.NoSuchElementException: key not found: 2
    at scala.collection.MapLike$class.default(MapLike.scala:228)
Était-ce utile?

La solution

Voici un chemin plus court que la question liée, tirée de ce fil:

  val f = Map("a" -> 1, "b" -> 2)                 

  val g = Map(1 -> 'c', 3 -> 'd')                 

  def andThenPartial[A, B, C](pf1: PartialFunction[A, B], pf2: PartialFunction[B, C]): PartialFunction[A, C] = {
    Function.unlift(pf1.lift(_) flatMap pf2.lift)
  }                                               

  val h = andThenPartial(f, g)            //> h  : PartialFunction[String,Char]

  h.isDefinedAt("a")                      //> res2: Boolean = true
  h.isDefinedAt("b")                      //> res3: Boolean = false
  h.lift("a")                             //> res4: Option[Char] = Some(c)
  h.lift("b")                             //> res5: Option[Char] = None

Cela peut également être intégré dans une classe implicite, bien sûr :

  implicit class ComposePartial[A, B](pf: PartialFunction[A, B]) {
    def andThenPartial[C](that: PartialFunction[B, C]): PartialFunction[A, C] =
      Function.unlift(pf.lift(_) flatMap that.lift)
  }

  val h2 = f andThenPartial g         //> h2  : PartialFunction[String,Char]

  h2.isDefinedAt("a")                 //> res6: Boolean = true
  h2.isDefinedAt("b")                 //> res7: Boolean = false
  h2.lift("a")                        //> res8: Option[Char] = Some(c)
  h2.lift("b")                        //> res9: Option[Char] = None

Autres conseils

val h = f.mapValues(g)

Mais cela ne fonctionne que pour les cartes.Je ne pense pas qu'il existe un moyen court de le faire pour tout type de fonction partielle, il vous suffira de créer manuellement un nouvel objet PartialFunction.

modifier:Je vois que mon code ci-dessus n'est pas celui que vous vouliez.Mais c'est peut-être mieux

val h = f.collect { case (k, v) if(g.contains(v)) => (k, g(v)) }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top