scala中的部分应用函数和偏函数的区别

来源:互联网 发布:texstudio mac 下载 编辑:程序博客网 时间:2024/06/07 10:02

经常把部分应用函数(Partial Applied Function)和偏函数(Partial Function) 搞混。下面做个总结:

  • 部分应用函数(Partial Applied Function)是缺少部分参数的函数,是一个逻辑上概念
  • 偏函数是只对函数定义域的一个子集进行定义的函数。 scala中用scala.PartialFunction[-T, +S]类来表示
比如定义了一个函数:def sum(x: Int)(y: Int) = x + y, 当调用sum的时候,如果不提供所有的参数或某些参数还未知时,比如sum _ , sum(3)(_: Int), sum(_: Int)(3), 这样就生成了所谓的部分应用函数。部分应用函数只是逻辑上的一个表达,scala编译器会用Function1, Function2这些类来表示它.

object Test extends App {  //部分应用函数  def sum(x: Int)(y: Int) = x + y    val sum1 = sum _  println(sum1(1)(2))         //3    val sum2 = sum(1) _ // val sum2 = sum(1)(_) // val sum2 = sum(1)(_:Int)  println(sum2(3))            //4    val sum3 = sum(_:Int)(4)  println(sum3(1))            //5  }


下面这个变量signal引用了一个偏函数

  val signal: PartialFunction[Int, Int] = {    case x if x > 0 => 1    case x if x < 0 => -1  }  println(signal(1))          //1  println(signal(0))          //MatchError

这个signal所引用的函数除了0值外,对所有整数都定义了相应的操作。 signal(0) 会抛出异常,因此使用前最好先signal.isDefinedAt(0)判断一下。 
偏函数主要用于这样一种场景:对某些值现在还无法给出具体的操作(即需求还不明朗),也有可能存在几种处理方式(视乎具体的需求);我们可以先对需求明确的部分进行定义,比如上述除了0外的所有整数域,然后根据具体情况补充对其他域的定义比如 
 val composed_signal: PartialFunction[Int, Int] = signal.orElse {  case 0 => 0  }  println(composed_signal(0)) //0
或者对定义域进行一定的偏移(假如需求做了变更,  1 为无效的点)
val new_signal: Function1[Int, Int] = signal.compose {    case x => x - 1  }  println(new_signal(2))      //1  println(new_signal(0))      //-1  println(new_signal(1))  //MatchError
还可以用andThen将两个相关的偏函数串接起来
<span style="color:#330033;">  val another_signal: PartialFunction[Int, Int] = {    case 0          => 0    case x if x > 0 => x - 1    case x if x < 0 => x + 1  }  val then_signal =  another_signal andThen  signal  //这里的then_signal 剔除了-1, 0, 1三个点的定义</span>

1 0