使用unapply功能丰富PartialFunction

时间:2015-10-17 02:54:06

标签: scala pattern-matching implicit-conversion

PartialFunction是一个自然提取器,其lift方法提供精确的提取器功能。因此,使用部分函数作为提取器非常方便。这将允许以比orElse

可用的普通PartialFunction更复杂的方式组合模式匹配表达式

所以我尝试使用pimp my library方法而且失败了

这里有更新:正如@Archeg所示,还有另一种转换方法可行。所以我将它包含在提供的代码中。

我也尝试了一些更复杂的解决方案而且失败了

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

我收到以下错误消息:

  

UnapplyImplicitly.scala:16:错误:值f不是案例类,也没有unapply / unapplySeq成员       case f(i)=>的println(ⅰ)

     

UnapplyImplicitly.scala:28:错误:'=>'预期但'''发现。       case toUnapply(f)(i)=>的println(ⅰ)

如果显示TestI所谓的形式,可以避免这种错误。但我很好奇是否可以避免testInplace错误:

  

UnapplyImplicitly.scala:46:错误:非法启动简单模式       case {case“bingo”=> 0} .u(i)=>的println(ⅰ)            ^

     

UnapplyImplicitly.scala:47:错误:'=>'预期,但';'找到。       case _ =>的println( “无”)

     

UnapplyImplicitly.scala:56:错误:'=>'预期,但'。'找到。       case g(“bingo”)。u(i)=>的println(ⅰ)                      ^

1 个答案:

答案 0 :(得分:4)

我不确定你到底想要实现什么,但据我所知,提取器应该总是对象,你无法用类来获得它。它实际上在文档中称为Extractor Object。考虑一下:

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")
}

<强>更新

我能想到的最好的:

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") }
}