Scala中的PartialFunction在Lift当中的NamedPF应用

首先看下PartialFunction(偏函数)如何在Lift当中使用的,先看下NamedPF静态类的代码:

class NamedPF[-A,+B](name: String, f: PartialFunction[A,B]) extends NamedPartialFunction[A,B] {
  override def isDefinedAt(x: A): Boolean = f.isDefinedAt(x)
  override def apply(x: A): B =f(x)
  val functionName = name
}

object NamedPF {

  def apply[A, B](name: String)(f: PartialFunction[A,B]): NamedPartialFunction[A,B]=
    new NamedPF(name,f)

  def find[A,B](value: A,list: Seq[PartialFunction[A,B]]):Option[PartialFunction[A,B]]=
    list.find(_.isDefinedAt(value))

  def isDefinedAt[A, B](value: A,list: Seq[PartialFunction[A,B]]):Boolean=
    find(value,list).isEmpty

  def apply[A, B](value: A, list: Seq[PartialFunction[A,B]]): B=
    find(value,list) match {
      case pf => pf.get.apply(value)
    }

  def applyBox[A, B](value: A,list: Seq[PartialFunction[A,B]]):Option[B]=
    find(value,list).map(_.apply(value))
}

 

NamedPF主要功能是在一个Seq[PartialFunction[A,B]]链表中找在FunctionName处有定义的PartialFunction.

想下这个应用场景,如果输入一个整数,有正数,负数,或者零,我们需要正数的时候对它进行某种操作,比如+2,如果是负数,就减2,如果是0,什么都不做。如果是C#语言的话 估计就是使用if else和委托来实现了。那么看下Scala当中是如何实现的,

object NamedPFTest{

  type CheckNum = PartialFunction[Int,(Int)=>Int]

  def main(args:Array[String]){
      val check:CheckNum={case n if n>0 =>(f:Int)=>n+f
                          case n if n==0 =>(f:Int)=>n}
      var pfList:List[CheckNum] = Nil
      pfList=check :: pfList
      val checkNeg:CheckNum={case n if n<0 => (f:Int)=>n-f}
      pfList=checkNeg :: pfList
      println(NamedPF.find(1,pfList).get.apply(3).apply(2))
      println(NamedPF.find(-1,pfList).get.apply(-7).apply(-2))
      println(NamedPF.find(0,pfList).get.apply(0).apply(0))
  }
}

 

首先定义一个type CheckNum=PartialFunction[Int,(Int)=>Int]类型,这里的第一个Int对应的是NamedPF[A,B]的A类型,(Int)=>Int对应的是B类型,它是一个参数为Int,返回Int类型的匿名函数, 然后我们定义了一个不可变变量check,类型就是CheckNum,

他的具体实现是

{case n if n>0 =>(f:Int)=>n+f
                          case n if n==0 =>(f:Int)=>n}
 
case n 中的n对应的就是PartialFunction[Int,(Int)=>Int]中的第一个Int,
(f:Int)=>n+f对应的就是(Int)=>Int
然后使用的方法代码是:
println(NamedPF.find(1,pfList).get.apply(3).apply(2))
println(NamedPF.find(-1,pfList).get.apply(-7).apply(-2))
println(NamedPF.find(0,pfList).get.apply(0).apply(0))

 

看下如何调用的:

NamedPF.find(-1,pfList),在pfList这个类型为PartialFunction[Int,(Int)=>Int]的链表中找到在-1处有定义的PartialFunction,返回类型是Option[PartialFunction[Int,(Int)=>Int],然后get,返回PartialFunction[Int,(Int)=>Int],再apply(3),这个3是PartialFunction[Int,(Int)=>Int]中的第一个Int,apply(3)之后返回的是(Int)=>Int 类型为Function1的匿名函数,再apply(2)就是调用(Int)=>Int函数了,返回类型为Int.

执行结果:

0G[Y$LQRY($~7EN1`7$UK{P

或者可以这样使用:

println(NamedPF.apply(1,pfList).apply(2))
println(NamedPF.apply(-1,pfList).apply(-2))
println(NamedPF.apply(0,pfList).apply(0))
 

PartialFunction在Lift使用的地方非常多,也是Scala一个非常重要的特性。
posted @ 2010-08-25 10:47  evilyzou  阅读(723)  评论(0)    收藏  举报