Scala入门之部分应用函数与偏函数

1.部分应用函数

部分应用函数(Partial Applied Function)是指缺少部分参数的函数.
package com.dt.scala.moguyun

/**
  * 部分应用函数
  * Created by Administrator on 2016/8/10.
  */
object PartialAppliedFunctionLearn {
  def main(args: Array[String]) {
    //第一种常见样式
    val result = sum _ //表明是一个部分应用函数,参数一个都没定
    val r = result(2)(3)(4)
    println(r)
    val r1 = result(1)//返回一个function1
    println(r1)
    val r2 = result(2)(_: Int)(4)
    println(r2)//返回一个function1
    val r3 = r2(5)//完整
    println(r3)

    //第二种常见样式
    val s = sum(4)(8)(_: Int)//注意这里得用_通配符,用i,j等不可以
    val s1 = s(7)
    println(s1)

    val s2 = sum(5)(_: Int)(_: Int)//返回一个function2
    println(s2)
    val s3 = s2(5, 3) //注意这里传入一个(Int, Int),而不是这样(5)(3)
    println(s3)
  }

  /**
    * 定义一个函数,要求传入三个Int类型参数
    */
  def sum(i: Int)(j: Int)(k: Int): Int ={
    i + j + k
  }
}

结果如下:

9
<function1>
<function1>
11
19
<function2>
13

2.偏函数

偏函数是只对函数定义域的一个子集进行定义的函数。这知识点是难点,自己也没能很好理解怎么用,什么时候用 -_-!
记得学线程的时候有个receive和react ,当时老师说这个是偏函数,也没懂什么意思。看源码
    def receive[R](f : scala.PartialFunction[scala.Any, R]) : R = { /* compiled code */ }
    override def react(handler : scala.PartialFunction[scala.Any, scala.Unit]) : scala.Nothing = 
这里的参数都是scala.PartialFunction类型的,泛型参数里第一个表示输入的类型,第二个表示输出的类型。
其实在下面代码中
class HelloActor extends Actor{
  override def act(): Unit = {
    while (true) {
      //receive从邮箱中获取一条消息
      //然后传递给它的参数
      //该参数是一个偏函数
      receive {
        case "actorDemo" => println("receive....ActorDemo")
      }
    }
  }
}

这里写图片描述
可以从上面图片中看出receive的参数是一个偏函数,输入参数是”actorDemo”,输出参数是Unit.可以理解case就是一个函数,经常有好多组case,如果一组case语句没有涵盖所有的情况,那么这组case语句就可以被看做是一个偏函数。
按我的理解,偏函数直接使用时像模式匹配,而偏函数作为参数传入时就难理解,更难应用。(以后再学怎么用),下面是自己写的代码,当作认识偏函数

package com.dt.scala.moguyun

/**
  * 偏函数
  * Created by hlf on 2016/8/10.
  */
object PartialFunctionLearn {
  def main(args: Array[String]): Unit = {
    jump("hello")
    //    jump(5)不是String直接报错
    //因为加了其余情况时会输出,如果不加其余情况的匹配会报错:
    //Exception in thread "main" scala.MatchErro
    jump("love")

    println(run(5))

    //定义时也可以用val来定义
    val jump2: PartialFunction[String, Unit] = {
      case "hello" => println("fine, and you?")
      case "have a good day!" => println("the same to you!")
      //    case 5 => println("why get me a Five?")
      case _ => println("what is this? get away from me!")
    }

    jump2("have a good day!")


  }

  /**
    * 定义一个偏函数,有两种方式定义偏函数,下面这种更好,
    * 因为有isDefinedAt方法来校验参数是否会得到处理.
    * 或者在调用时使用一个orElse方法,该方法接受另一个偏函数,
    * 用来定义当参数未被偏函数捕获时该怎么做
    */
  def jump: PartialFunction[String, Unit] = {
    case "hello" => println("fine, and you?")
    case "have a good day!" => println("the same to you!")
    //    case 5 => println("why get me a Five?")
    case _ => println("what is this? get away from me!")//注释的话如果匹配不上会报错
  }


  /**
    * 另一种定义一个偏函数的方式,不细说
    */
  def run = (x: Int) => x match {
    case x if x > 1 => 1
  }


}
结果
fine, and you?
what is this? get away from me!
1
the same to you!

什么时候该使用偏函数?
当我们确定我们的程序不会被传入不可处理的值时,我们就可以使用偏函数。这样万一程序被传入了不应该被传入的值,程序自动抛出异常,而不需要我们手工编写代码去抛出异常,减少了我们的代码量。(不全)

3.蘑茹云代码

package com.dt.spark.scala.bascis

object HelloPartionalFunction {
  def main(args: Array[String]): Unit = {
    val sample =1 to 10
    val isEven:PartialFunction[Int,String]={
      case x if x % 2 == 0 =>   x + "is even" 
        }
    isEven(4)
    val evenNumbers = sample collect isEven
    evenNumbers.foreach { println }
     val isOdd:PartialFunction[Int,String]={
      case x if x % 2 == 1 =>   x + "is Odd" 
        }

     val numbers =sample map {isEven orElse isOdd}
     numbers.foreach { println }
  }
}





2is even
4is even
6is even
8is even
10is even
1is Odd
2is even
3is Odd
4is even
5is Odd
6is even
7is Odd
8is even
9is Odd
10is even

以上蘑茹云代码来自[DT大数据梦工厂]首席专家Spark专家王家林老师的课程分享。感谢王老师的分享,更多精彩内容请扫描关注[DT大数据梦工厂]微信公众号DT_Spark

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值