enrich PartialFunction with unapply functionality

筅森魡賤 提交于 2019-12-10 18:56:06

问题


PartialFunction is a natural extractor, its lift method provides exact extractor functionality. So it would be very convenient to use partial functions as extractors. That would allow to combine pattern matching expressions in more complicated way than plain orElse that is available for PartialFunction

So I tried to use pimp my library approach and had failed


Here goes update: As @Archeg shown, there is another approach to conversion that works. So I'm including it to the provided code.

I'm tried also some more complex solutions and they failed


object Test {
  class UnapplyPartial[-R, +T](val fun : PartialFunction[R,T]) {
    def unapply(source : R) : Option[T] = fun.lift(source)
  }
  implicit def toUnapply[R,T](fun : PartialFunction[R,T]) : UnapplyPartial[R,T] = new UnapplyPartial(fun)

  class PartialFunOps[-R, +T](val fun : PartialFunction[R,T]) {
    def u : UnapplyPartial[R, T] = new UnapplyPartial(fun)
  }
  implicit def toPartFunOps[R,T](fun : PartialFunction[R,T]) : PartialFunOps[R,T] = new PartialFunOps(fun)


  val f : PartialFunction[String, Int] = {
    case "bingo" => 0
  }
  val u = toUnapply(f)

  def g(compare : String) : PartialFunction[String, Int] = {
    case `compare` => 0
  }

   // error while trying to use implicit conversion
  def testF(x : String) : Unit = x match {
    case f(i) => println(i)
    case _ => println("nothing")
  }

  // external explicit conversion is Ok
  def testU(x : String) : Unit = x match {
    case u(i) => println(i)
    case _ => println("nothing")
  }

 // embedded explicit conversion fails
  def testA(x : String) : Unit = x match {
    case toUnapply(f)(i) => println(i)
    case _ => println("nothing")
  }

  // implicit explicit conversion is Ok
  def testI(x : String) : Unit = x match {
    case f.u(i) => println(i)
    case _ => println("nothing")
  }

  // nested case sentences fails
  def testInplace(x : String) : Unit = x match {
    case { case "bingo" => 0 }.u(i) => println(i)
    case _ => println("nothing")
  }

  // build on the fly fails
  def testGen(x : String) : Unit = x match {
    case g("bingo").u(i) => println(i)
    case _ => println("nothing")
  }

  // implicit conversion without case is also Ok
  def testFA(x : String) : Option[Int] =
    f.unapply(x)
}

I got the following error messages:

UnapplyImplicitly.scala:16: error: value f is not a case class, nor does it have an unapply/unapplySeq member case f(i) => println(i)

UnapplyImplicitly.scala:28: error: '=>' expected but '(' found. case toUnapply(f)(i) => println(i)

This errors may be avoided with supposed form as TestI shown. But I'm curious if it is possible to avoid testInplace error:

UnapplyImplicitly.scala:46: error: illegal start of simple pattern case { case "bingo" => 0 }.u(i) => println(i) ^

UnapplyImplicitly.scala:47: error: '=>' expected but ';' found. case _ => println("nothing")

UnapplyImplicitly.scala:56: error: '=>' expected but '.' found. case g("bingo").u(i) => println(i) ^


回答1:


I'm not sure what you are trying to achieve in the end, but as far as I understand extractors should always be objects, there is no way you can get it with a class. It is actually called Extractor Object in the documentation. Consider this:

class Wrapper[R, T](fun: PartialFunction[R, T]) {
  object PartialExtractor {
    def unapply(p: R): Option[T] = fun.lift(p)
  }
}

implicit def toWrapper[R,T](fun : PartialFunction[R,T]) : Wrapper[R, T] = new Wrapper(fun)


val f : PartialFunction[String, Int] = {
  case "bingo" => 0
}

def testFF(x : String) : Unit = x match {
  case f.PartialExtractor(i) => println(i)
  case _ => println("nothing")
}

Update

The best I could think of:

def testInplace(x : String) : Unit ={
  val ff = { case "bingo" => 0 } : PartialFunction[String, Int]
  x match {
   case ff.PartialExtractor(Test(i)) => println(i)
   case "sd" => println("nothing") }
}


来源:https://stackoverflow.com/questions/33182235/enrich-partialfunction-with-unapply-functionality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!