Scala中有一个很有用的traits叫PartialFunction,我看了下别人的翻译叫做偏函数,但是我觉得部分函数更加确切。 那么PartialFunction是做什么用的呢? 我们先看下PartialFunction的定义: trait PartialFunction[-A, +B] extends (A => B) { ... 也定义了一个方法:def isDefinedAt(x: A): Boolean 如果我们要自己实现一个PartialFunction,则必须实现上述两个方法: val inc = new PartialFunction 我们看下这几个PartialFunction该怎么定义: val isVeryTasty: PartialFunction[String, String] = { case "Glazed 这里使用case语句,会自动转换成为PartialFunction。
在Scala中,所有偏函数的类型皆被定义为PartialFunction[-A, +B]类型,PartialFunction[-A, +B]又派生自Function1。 PartialFunction的定义如下所示: trait PartialFunction[-A, +B] extends (A => B) { self => import PartialFunction case语句从本质上讲就是PartialFunction的子类。 当我们定义了如下值: val p:PartialFunction[Int, String] = { case 1 => "One" } 实际上就是创建了一个PartialFunction[Int, String 这个empty等于类型为PartialFunction[Any, Nothong]的值empty_pf,定义如下: private[this] val empty_pf: PartialFunction
Scala中的Partia Function是一个Trait,其的类型为PartialFunction[A,B],其中接收一个类型为A的参数,返回一个类型为B的结果。 scala> val onePF:PartialFunction[Int,String] = { | case 1=>"One" | } onePF: PartialFunction | } twoPF: PartialFunction[Int,String] = <function1> scala> val threePF:PartialFunction[Int,String] otherPF:PartialFunction[Int,String] = { | case _=>"Other" | } otherPF: PartialFunction[Int scala> val pf1:PartialFunction[Int,String] = { | case i if i == 1 => "One" | } pf1: PartialFunction
而对于collect,它声明接受的是一个偏函数:PartialFunction,传递的case语句能良好的工作说明这个case语句被编译器自动编译成了一个PartialFunction! (注意:PartialFunction同时是Function1的子类)编译器会根据调用处的函数类型声明自动帮我们判定如何编译这个case语句(组合)。 所以特质PartialFunction就被创建出来用于“标记”这类函数的,这个特质最主要的方法就是isDefinedAt! 同时你也记得PartialFunction还是Function1的子类,所以它也要有apply方法,这是非常自然的,偏函数本身首先是一个函数嘛。 说到底,类型PartialFunction无非是为由一组case语句描述的函数字面量提供一个类型描述而已,case语句只接受一个参数,则偏函数的类型声明自然就只有一个参数。
TraversableOnce[A]): Seq[A] 原理与 map 一致,只是 f 变成了 BaseType => TraversableOnce[A] 2.5、collect[B](pf: PartialFunction [BaseType, B]): Seq[B] def collect[B](pf: PartialFunction[BaseType, B]): Seq[B] = { val ret = [B] 以 Seq 形式返回 2.6、collectLeaves(): Seq[BaseType] 以 Seq 的形式返回 tree 的所有叶子节点 def collectFirst[B](pf: PartialFunction 2.9、transform(rule: PartialFunction[BaseType, BaseType]): BaseType 调用 transformDown 2.10、transformDown (rule: PartialFunction[BaseType, BaseType]): BaseType rule: PartialFunction[BaseType, BaseType] def
trait PartialFunction[-A, +B] extends (A => B) { self => import PartialFunction._ def isDefinedAt (x: A): Boolean def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = new OrElse[A1, B1] (this, that) override def andThen[C](k: B => C): PartialFunction[A,
CaseStatements.scala:26) at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:21) at scala.PartialFunction $class.applyOrElse(PartialFunction.scala:123) at akka.japi.pf.UnitCaseStatement.applyOrElse(CaseStatements.scala :21) at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:170) at scala.PartialFunction $OrElse.applyOrElse(PartialFunction.scala:171) at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala
*/ def seal(settings: RoutingSettings): ExceptionHandler } object ExceptionHandler { type PF = PartialFunction ne null) handler.seal(settings) else ExceptionHandler.default(settings) } 简单来说ExceptionHandler类型就是一种PartialFunction : trait ExceptionHandler extends PartialFunction[Throwable, Route] 因为ExceptionHandler就是PartialFunction
偏函数定义 val second: PartialFunction[List[Int], Option[Int]] = { case x :: y :: _ => Some(y) } second:偏函数名称 PartialFunction[List[Int], Option[Int]]: 偏函数类型 该偏函数的功能是返回输入的 List 集合的第二个元素 举个例子: object Test_PartialFunction list.map { case (word, count) => (word, count * 2) } // 函数应用 求绝对值 val positiveAbs: PartialFunction [Int, Int] = { case x if x >= 0 => x } val pnegativeAbs: PartialFunction[Int, Int] = {
方法以及AnalysisHelper 中的 resolveOperatorsUp方法 等 这两个方法类似,以TreeNode 中的 transformUp为例: def transformUp(rule: PartialFunction newNode = if (this fastEquals afterRuleOnChildren) { CurrentOrigin.withOrigin(origin) { //这里用到了PartialFunction 方法以及AnalysisHelper 中的 resolveOperatorsDown方法 等 TreeNode 中的 transformDown为例: def transformDown(rule: PartialFunction 主要通过AnalysisHelper 中的 resolveOperatorsUp(后序遍历的)方法: // 入参为rule,偏函数 def resolveOperatorsUp(rule: PartialFunction resolveOperatorsDown方法: /** Similar to [[resolveOperatorsUp]], but does it top-down. */ def resolveOperatorsDown(rule: PartialFunction
cache函数是这样定义的; def cache[K](cache: Cache[K, RouteResult], keyer: PartialFunction[RequestContext, K]): RouteResult](cachingSettings) //Example keyer for non-authenticated GET requests val simpleKeyer: PartialFunction > Boolean = // _.request.headers.exists(_.is(Authorization.lowercaseName)) val result: PartialFunction
rpcEnv.endpointRef(this) } //处理来自RpcEndpointRef.send或者RpcCallContext.reply的消息 def receive: PartialFunction receive'") } //处理来自RpcEndpointRef.ask的消息,会有相应的回复 def receiveAndReply(context: RpcCallContext): PartialFunction 上文可以看到,在RpcEndpoint中最核心的便是receive和receiveAndReply方法,定义了消息处理的核心逻辑,master中也有相应的实现: override def receive: PartialFunction > } 这里定义了master一系列的消息处理逻辑,而receiveAndReply中, override def receiveAndReply(context: RpcCallContext): PartialFunction
CaseStatements.scala:26) at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:21) at scala.PartialFunction.applyOrElse (PartialFunction.scala:123) at scala.PartialFunction.applyOrElse$(PartialFunction.scala:122) at akka.japi.pf.UnitCaseStatement.applyOrElse (CaseStatements.scala:21) at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:171) at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:172) at scala.PartialFunction$OrElse.applyOrElse (PartialFunction.scala:172) at akka.actor.Actor.aroundReceive(Actor.scala:517) at akka.actor.Actor.aroundReceive
msg}") } } object Supervisor { def props: Props = { //在这里定义了监管策略和child Actor构建 def decider: PartialFunction 注意:我们同时把ChildException改成了一个带参数的class,因为我们可能需要在重启之前获取造成异常的消息,如下: def decider: PartialFunction[Throwable 下面我们来解决失踪消息的问题:首先是如何重新发送造成异常的消息,我们可以在监管策略中重启前发送: def decider: PartialFunction[Throwable, SupervisorStrategy.Directive msg}") } } object Supervisor { def props: Props = { //在这里定义了监管策略和child Actor构建 def decider: PartialFunction
def receiveMessage[T](onMessage: T => Behavior[T]): Receive[T] def receivePartial[T](onMessage: PartialFunction [(ActorContext[T], T), Behavior[T]]): Receive[T] def receiveMessagePartial[T](onMessage: PartialFunction [T, Behavior[T]]): Receive[T] def receiveSignal[T](handler: PartialFunction[(ActorContext[T], Signal 它们还是Behavior[T]: trait Receive[T] extends Behavior[T] { def receiveSignal(onSignal: PartialFunction
iproc是个函数,而partialfunction是function的子类,因而可以这样写 7 case None => iproc(None) //没有输入元素,继续等 (Some(i))) //更新了状态,但未完成流程,不算一次重复 22 } 23 } 24 go(n,this) 25 } 注意我们在以上代码中使用了PartialFunction 如果我们有个Function : intFunction(i: Int): String 我们可以定义它的PartialFunction: { case 0: "Zero" case 10: "Ten " } 由于Await(iproc)中的iproc >>> Option[I] => Process[I,O], PartialFunction是Function的子类所以我们可以写成: Await { iproc是个函数,而partialfunction是function的子类,因而可以这样写 58 case None => iproc(None) //没有输入元素,
private val stateFunctions = mutable.Map[S, StateFunction]() 而StateFuction是: type StateFunction = scala.PartialFunction 也可以包括状态转换处理函数TransitionHandler: type TransitionHandler = PartialFunction[(S, S), Unit] 最后,initialize FSM DSL中的transform是这样定义的: final class TransformHelper(func: StateFunction) { def using(andThen: PartialFunction TransformHelper = new TransformHelper(func) 我们看到TransformHelper用using对入参func:StateFunction施用用户提供的andThen: PartialFunction m stay } using targetTransformer } def targetTransformer: PartialFunction[State, State
TableEnvironment): LogicalNode = { val node = super.resolveExpressions(tableEnv).asInstanceOf[Join] val partialFunction : PartialFunction[Expression, Expression] = { case field: ResolvedFieldReference => JoinFieldReference left, right) } val resolvedCondition = node.condition.map(_.postOrderTransform(partialFunction
TableEnvironment): LogicalNode = { val node = super.resolveExpressions(tableEnv).asInstanceOf[Join] val partialFunction : PartialFunction[Expression, Expression] = { case field: ResolvedFieldReference => JoinFieldReference left, right) } val resolvedCondition = node.condition.map(_.postOrderTransform(partialFunction
定义 偏函数被包在花括号内没有match的一组case语句是一个偏函数 偏函数是PartialFunction[A, B]的一个实例 – A代表输入参数类型 – B代表返回结果类型 示例一