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) ^