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

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
The Last Watchdog
The Last Watchdog
Cyberwarzone
Cyberwarzone
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Cloudflare Blog
V
V2EX
博客园_首页
博客园 - 聂微东
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
T
Tenable Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
SecWiki News
SecWiki News
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
D
DataBreaches.Net
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
D
Docker
P
Proofpoint News Feed

博客园 - 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一个非常重要的特性。