Scala-偏函数与部分应用函数

scala中有PartialFunction的概念, 同时还要一个概念叫Partial Applied Function. 前者译作偏函数, 后者译作"偏应用函数"或"部分应用函数", 一字之差, 差距很大.

1.偏函数

首先我们介绍样本序列(Case sequences),从而具体介绍什么是偏函数。样本序列是一种特殊的函数,通常情况下函数只有一个入口,但是样本序列会有多个函数入口。比如下面的列子:
val withDefault: Option[Int] => Int = {
      case Some(x) => x
      case None => 0
}
withDefault是一个(Option[Int] => Int)类型的方法,这个方法体包含2个case.第一个匹配Some类型,第二个匹配None类型
scala> withDefault(Some(10))
res28: Int = 10
  
scala> withDefault(None)
res29: Int = 0
这种方法的使用在Akka的actor中经常使用到,比如actor中的receive方法
def receive = {
    case Data(byte) =>
      sum += byte
  
    case GetChecksum(requester) =>
      val checksum = ~(sum & 0xFF) + 1
      requester ! checksum
}
如果,你传递的参数值是case里面无法匹配的,它将会产生一个运行时的异常,比如
val second: List[Int] => Int = {
	case x :: y :: _ => y
}

scala> second(List())
scala.MatchError: List()
	at $anonfun$1.apply(<console>:17)
	at $anonfun$1.apply(<console>:17)
注意此时的second还仅是一个函数类型,具体来说它是一个function1类型 ,如果你想定义一个偏函数函数必须进行如下的声明 (function1和PartialFunction的区别稍后讲解)
val second2: PartialFunction[List[Int],Int] = {
  case x :: y :: _ => y
}
事实上,这个字面函数 { case x :: y :: _ => y }在编译时会翻译成下面的语句,但是如果你的类型声明是Funtion1或者缺失,它可能会翻译成一个不完整的函数,所以推荐使用完整的
PartialFunction声明,如上面的例子
new PartialFunction[List[Int], Int] {
  def apply(xs: List[Int]) = xs match {
	case x :: y :: _ => y
  }

  def isDefinedAt(xs: List[Int]) = xs match {
	case x :: y :: _ => true
	case _ => false
  }
}
只有当isDefinedAt方法返回为true是,apply方法才会去执行,此时我们可以添加额外的逻辑,比如过滤掉某些不符合条件的东东
val list=List(List(1,2),List(1))
val r1=list.collect(second2) //collect有个重载的方法参数为PartialFunction
println(r1) //List(2)

function1和PartialFunction的区别

其实官方的API解释得很明朗,通俗点来说平时我们使用的拉姆达表达式就是FunctionX提供给我们的语法糖,二者的功能完全一样。事实上,PartialFunction是Funtion1的子类,只不过Funtion1仅仅只是一个函数,而PartialFunction可以识别出我们的输入,并进行一些额外的处理

A function of 1 parameter.

In the following example, the definition of succ is a shorthand for the anonymous class definition anonfun1:

 object Main extends App {
   val succ = (x: Int) => x + 1
   val anonfun1 = new Function1[Int, Int] {
     def apply(x: Int): Int = x + 1
   }
   assert(succ(0) == anonfun1(0))
}

Note that the difference between Function1 and scala.PartialFunction is that the latter can specify inputs which it will not handle.

 

2.部分应用函数

部分应用函数, 是指一个函数有N个参数, 而我们为其提供少于N个参数, 那就得到了一个部分应用函数. 

比如我先定义一个函数

 

def sum(a:Int,b:Int,c:Int) = a + b + c; 

那么就可以从这个函数衍生出一个偏函数是这样的:

def p_sum = sum(1, _:Int, _:Int)

于是就可以这样调用p_sum(2,3), 相当于调用sum(1,2,3) 得到的结果是6. 这里的两个_分别对应函数sum对应位置的参数. 所以你也可以定义成

def p_sum = sum (_:Int, 1, _:Int) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值