Frage

Ich habe zwei Teilfunktionen f und g.Sie haben keine Nebenwirkungen und sind schnell auszuführen.Was ist der beste Weg, um sie zu einer anderen Teilfunktion zusammenzusetzen h so dass h.isDefinedAt(x) iff f.isDefinedAt(x) && g.isDefinedAt(f(x))?

Es ist auch in Ordnung, wenn h ist eine Funktion, die eine zurückgibt Option eher als eine Teilfunktion.

Ich bin enttäuscht, dass f andThen g macht nicht was ich will:

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)
War es hilfreich?

Lösung

Hier ist ein kürzerer Weg als die verknüpfte Frage, entnommen aus dieser Thread:

  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

Dies kann natürlich auch als implizite Klasse zusammengefasst werden:

  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

Andere Tipps

val h = f.mapValues(g)

Das funktioniert aber nur für Karten.Ich glaube nicht, dass es einen kurzen Weg gibt, dies für irgendeine Art von Partialfunktion zu tun, Sie müssen nur manuell ein neues PartialFunction Objekt erstellen.

bearbeiten:Ich sehe, dass mein obiger Code nicht das ist, was Sie wollten.Aber vielleicht ist das besser

val h = f.collect { case (k, v) if(g.contains(v)) => (k, g(v)) }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top