高阶函数

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

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. mac出现zsh: command not found: ping解决方法

    Step1:终端输入以下命令: /sbin/ping 若出现如下信息,说明包含ping命令,是zsh的 PATH有问题,表示没有加载sbin下的命令,需要编辑.zshrc文件. Step2:终端打开. ...

  2. linux基础之bash特性

    linux基础之bash特性 1.命令历史 命令历史包含的环境变量 $HISTSIZE:命令历史记录的条数 $HISTFILE:命令历史文件~/.bash_history $HISTFILESIZE: ...

  3. switch语句判断学生成绩

    下面通过判断学生成绩来展示switch语句的使用. Q:判断学生成绩的等级,90-100分为A级,80-89为B级,70-79为C级,60-69为D级,60以下不及格. package main im ...

  4. Lock的lockInterruptibly()方法

    lockInterruptibly()方法能够中断等待获取锁的线程.当两个线程同时通过lock.lockInterruptibly()获取某个锁时,假若此时线程A获取到了锁,而线程B只有等待,那么对线 ...

  5. InnoDB存储引擎文件

    InnoDB存储引擎文件 MySQL数据库包括数据库本身的文件和存储引擎文件.数据库自身的文件由参数文件(my.cnf).错误日志文件.慢查询日志文件.查询日志文件.二进制日志文件.套接字文件.pid ...

  6. JavaScript获取mp4文件MIME编码格式,用于判读是否是h.264,解决在线播放只有声音问题

    测试网址:https://gpac.github.io/mp4box.js/test/filereader.html js库:mp4box.js 不能在线播放的:audio/mp4; codecs=& ...

  7. anaconda 在内网中代理配置

    修改anaconda的配置文件,位置在c:\User(或“用户”)\current_user(当前用户)\.condarc,将以下内容拷贝进去, 替换原有内容, 修改 http://proxy.you ...

  8. 【python】如何将ipdb的python解释器路径切换至虚拟环境中

    背景: 利用virtualenv构建一个python3.5的虚拟环境,在该虚拟环境中使用ipdb调试程序,结果报错找不到某一个模块. 程序的所有依赖模块都已经成功安装在虚拟环境中. 在虚拟环境中,te ...

  9. SQL 语句 explain 分析

      分析索引的效率: > EXPLAIN sql; EXPLAIN 分析的结果的表头如下: id | select_type | table | partitions | type | poss ...

  10. 初始nginx(启动运行) 使用nginx做一个简单的静态资源服务器

    第一次接触nginx的时候,那时候公司还是用的一些不知名的小技术,后来公司发展问题,重新招了人,然后接触到nginx,公司 使用nginx用来做代理服务器,所有请求 都先经过nginx服务器,然后交由 ...