高阶函数

高阶函数就是将函数作为参数或者返回值的函数。

object function {

  def main(args: Array[String]): Unit = {
println(test(f,10))
} def test(f:Int => String , num : Int) = f(num) def f(num:Int) : String = {
10 + num + ""
} }

在spark中,经常将只需要执行一次的函数定义为匿名函数作为参数传递给高阶函数。如map,flatMap。

以map为例,最全面的写法是

object function {
def main(args: Array[String]): Unit = {
val list = List("spark","hadoop","hbase")
list.map(f2:String=>(String,Int)).foreach(println)
}
def f(x:String) : (String,Int) = {
(x,1)
}
}

匿名函数的写法

list.map((x:String) => (x,1)).foreach(println)

利用匿名函数的参数推断,可以进一步简化的写法

list.map((x) => (x,1)).foreach(println)

如果只有一个参数

list.map(x => (x,1)).foreach(println)

可以使用_代替参数

list.map((_,3)).foreach(println)

偏应用函数

偏应用函数指的是如果一个函数有n个参数,为其提供少于n个参数的函数叫做偏应用函数。又叫做部份函数。其实也点类似于方法重载。

  def f1(x:Int,y:Int,z:Int) = x+y+z

  def f2(y:Int,z:Int) = f1(1,y,z)

偏函数

scala里的偏函数也是数学中的一个概念,指定义域X中可能存在某些值在值域Y中没有对应的值,通俗点说就是入参是在指定的范围内,因此它比普通的函数多了个isDefinedAt方法,用于判断参数是否在该函数的接受范围内。不同于普通函数,偏函数是scala.PartialFunction[-A,+B]的对象。

先看一个例子

//这是一个偏函数
val pf: PartialFunction[Int, String] = {
case 1 => "One"
case 2 => "Two"
case 3 => "Three"
} //这不是一个偏函数
val pf2: PartialFunction[Int, String] = {
case 1 => "One"
case 2 => "Two"
case 3 => "Three"
case _ => "else"
} println(pf(1)) //One
println(pf2(4)) //else
println(pf(4)) //异常

偏函数的定义

PartialFunction[Int, String] 
Int为输入类型,String为返回值类型。

pf的定义域为所有int,值域为【1,2,3】,除了【1,2,3】以外的参数并没有与之对应的返回值。所以pf是一个偏函数。调用偏函数传入定义域以外的参数就会报错,但是偏函数提供了其它的方法来避免这种情况。

使用isDefinedAt来判断是否可以传入此参数,返回一个布尔值。

println(pf.isDefinedAt(4)) //false

orElse相当于连接。条件是两个偏函数的类型是一样的。

val pf: PartialFunction[Int, String] = {
case 1 => "One"
case 2 => "Two"
case 3 => "Three"
} val pf2: PartialFunction[Int, String] = {
case 4 => "Four"
case 5 => "Five"
case 6 => "Six"
} pf orElse pf2相当于 val pf: PartialFunction[Int, String] = {
case 1 => "One"
case 2 => "Two"
case 3 => "Three"
case 4 => "Four"
case 5 => "Five"
case 6 => "Six"
}

andThen

对函数的结果进行下一步的处理。前提是前一个的偏函数返回值类型是后一个偏函数的输入类型。如,上面两个函数就是报错。
    pf andThen pf3
pf3 andThen pf//异常 val pf2: PartialFunction[Int, String] = {
case 1 => "One"
case 2 => "Two"
case 3 => "Three"
case _ => "else"
} val pf3: PartialFunction[String, String] = {
case "One" => "One"
case "Two" => "Two"
case "Three" => "Three"
case "else" => "else"
}

偏函数的意义在于粒度的问题。可以把一个函数细分,然后在不同的功能的时候对这些函数进行排列组合,自由灵活的达到想要的功能。

柯里化

看代码最直观

  def add(x:Int,y:Int,z:Int) = x+y+z
def add2(x:Int)(y:Int)(z:Int) = x+y+z

函数add到add2的过程就是柯里化。两个函数参数类型个数和返回值都是一样的。但是过程不一样。

函数add直接相加。

函数add2先演变为

val result = add2(x)

再演变为

val  add2(y:Int) = result + y
val result2 = add2(y)

最后是

val add2(z:Int) = result2 + z
val result3 = add2(z)

关于其应用及其意义,参照fold,aggregate。

闭包

闭包函数返回值依赖于函数外部的变量。

  val y : Int = 0
def f(x:Int) = x + y
println(f(10))

我们定义了一个形参x,调用的时候传入,另一个函数外部的变量y,是一个自由变量。这样就定义了一个闭包。因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。

spark快速开发之scala基础之5高阶函数,偏函数,闭包的更多相关文章

  1. spark快速开发之scala基础之1 数据类型与容器

    写在前面 面向java开发者.实际上,具有java基础学习scala是很容易.java也可以开发spark,并不比scala开发的spark程序慢.但学习scala可有助于更快更好的理解spark.比 ...

  2. spark快速开发之scala基础之3类,对象,特征

    类 scala的类定义非常灵活 class test4 class test2{} class test3(x:Int) 定义一个带构造函数的类 class Point (x : Int,y : In ...

  3. spark快速开发之scala基础之2控制流程

    判断结构 大体与java相当.scala没有三元表达式. val num = if(1>0) 1 else 0 //相当于匿名函数 println(num) var num2 = 0 if(1& ...

  4. python 基础 4.3 高阶函数下和匿名函数

    一 .匿名函数 顾名思议就是没有名字的函数,那为什么要设立匿名函数,他有什么作用呢?lambda 函数就是一种快速定义单行的最小函数,可以用在任何需要函数的地方.   常规版: def fun(x,y ...

  5. Scala学习十二——高阶函数

    一.本章要点 在Scala中函数是”头等公民“(可以作为参数,返回值,赋值给其他); 可以创建匿名函数,通常还会交给其他函数; 函数参数可以给出需要稍后执行的行为; 许多集合方法都接受函数参数,将函数 ...

  6. scala学习笔记:高阶函数

    scala> def power(y:Double)=(x:Double)=>Math.pow(x,y) warning: there were 1 deprecation warning ...

  7. python 基础 4.2 高阶函数上

    一.高阶函数 把函数当做参数传递的一种函数   1>map()函数 map函数是python内置的一个高阶函数,它接受一个函数f和一个list,并把list元素以此传递给函数f,然后返回一个函数 ...

  8. Scala集合操作中的几种高阶函数

    Scala是函数式编程,这点在集合操作中大量体现.高阶函数,也就是能够接收另外一个函数作为参数的函数. 假如现在有一个需要是将List集合中的每个元素变为原来的两倍,现在来对比Java方式实现和Sca ...

  9. Scala高阶函数与泛型

    1. Scala中的函数 在Scala中,函数是“头等公民”,就和数字一样.可以在变量中存放函数,即:将函数作为变量的值(值函数). 2. scala中的匿名函数,即没有函数名称的函数,匿名函数常作为 ...

随机推荐

  1. java.lang.ClassNotFoundException: org.apache.http.conn.UnsupportedSchemeException

    加入了阿里云的消息服务后,就一直之前报java.lang.ClassNotFoundException: org.apache.http.conn.UnsupportedSchemeException ...

  2. 本文档教授大家在yii2.0里实现文件上传 首先我们来实现单文件上传

    第一步  首先建立一个关于上传的model层  如果你有已经建好的可以使用表单小部件的model层 也可以直接用这个.在这里我们新建一个新的model层 在model层新建文件  Upload.php ...

  3. java-Set集合、HashSet集合、LinkedHashSet集合和TreeSet集合

    1.Set集合,无索引,不可以重复,无序(存取不一致) public class Demo { public static void main(String[] args) { //demo1(); ...

  4. (转)python logging模块

    python logging模块 原文:http://www.cnblogs.com/dahu-daqing/p/7040764.html 1 logging模块简介 logging模块是Python ...

  5. Python 面向对象编程(进阶部分)

    静态方法: 通过 @staticmethod 装饰器即可把其装饰的方法变为一个静态方法.普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实 ...

  6. shell脚本实现定时备份某文件

    1:目标       实现在图像化界面输入需要备份的源文件路径.目标路径,定时的时间.然后通过输入的信息,把需要备份的源文件打包放到指定的目标路径下以执行定时任务的时间为子目录       把/she ...

  7. Spring Boot - 基础 POM 文件

    表 1. Spring Boot 推荐的基础 POM 文件 名称 说明 spring-boot-starter 核心 POM,包含自动配置支持.日志库和对 YAML 配置文件的支持. spring-b ...

  8. python虚拟环境virtualenv简介

    参考网站: https://realpython.com/python-virtual-environments-a-primer/ 一. 创建一个新的虚拟环境 # Python 2: $ virtu ...

  9. EXCEL统计不重复值的数量

    如这一列中,有多少不重复值? 1.可以点击,数据,删除重复项,清除重复值,然后剩下的统计一下即可知道:       ===> 2.用公式:=SUMPRODUCT((MATCH(E3:E20,E3 ...

  10. 简述Ajax原理及实现步骤

    简述Ajax原理及实现步骤 1.Ajax简介 概念 Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML). 现在允许浏览器与务器通信 ...