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.
执行结果:
或者可以这样使用:
println(NamedPF.apply(1,pfList).apply(2)) println(NamedPF.apply(-1,pfList).apply(-2)) println(NamedPF.apply(0,pfList).apply(0))
PartialFunction在Lift使用的地方非常多,也是Scala一个非常重要的特性。