惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Security Blog
Microsoft Security Blog
Jina AI
Jina AI
量子位
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家
S
SegmentFault 最新的问题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
雷峰网
雷峰网
博客园 - 聂微东
美团技术团队
Last Week in AI
Last Week in AI
罗磊的独立博客
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园_首页
V
Visual Studio Blog
大猫的无限游戏
大猫的无限游戏
The Cloudflare Blog

博客园 - evilyzou

scala 的List foldLeft用法 Circumflex Scala中的Either的两个子类(Left,Right)的简单用法 Scala中的一些特殊字符用法 Lift当中的AnyVarTrati源码解析 scala的DynamicVariable用法 SBT和IDEA 开发scala web程序 使用Sbt(一) scalatra web框架安装指南 ASP.NET MVC: Do You Know Where Your TempData Is? 使用IntelliJ IDEA, Maven and the jetty plugin调试web应用程序 Scala GraphViz DOT Parser Scala Standard library Scala 一些基本的语法 Scala 相关的资源和Blog Lift2.0发布 Linux 汇编语言开发指南 Linux2.6内核启动流程学习 [导入]C#强化系列文章五:动态代码的使用(反射和动态生成类) [导入]C#强化系列文章七:序列化和反序列化
Scala中的PartialFunction在Lift当中的NamedPF应用
evilyzou · 2010-08-25 · via 博客园 - evilyzou

首先看下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一个非常重要的特性。