函数式编程基础

函数定义和高阶函数

函数字面量
  • 字面量包括整数字面量、浮点数字面量、布尔型字面量、字符字面 量、字符串字面量、符号字面量、函数字面量和元组字面量。

scala> val i = 123
i: Int = 123
​
scala> val i = 3.14
i: Double = 3.14
​
scala> val i = true
i: Boolean = true
​
scala> val i = 'A'
i: Char = A
​
scala> val i = "Hello"
i: String = Hello
  • 除了函数字面量我们会比较陌生以外,其他几种字面量都很容易理解。

  • 函数字面量可以体现函数式编程的核心理念

  • 在非函数式编程语言里,函数的定义包含了“函数类型”和“值”两种层 面的内容

  • 但是,在函数式编程中,函数是“头等公民”,可以像任何其他数据类型 一样被传递和操作,也就是说,函数的使用方式和其他数据类型的使用方 式完全一致了

  • 这时,我们就可以像定义变量那样去定义一个函数,由此导致的结果是, 函数也会和其他变量一样,开始有“值”

  • 就像变量的“类型”和“值”是分开的两个概念一样,函数式编程中,函数的“类型”和“值”也成为两个分开的概念,函数的“值”,就是“函数字面量"

  • 下面我们一点点引导大家更好地理解函数的“类型”和“值”的概念。 我们现在定义一个大家比较熟悉的传统类型的函数,定义的语法和我们之前介绍 过的定义“类中的方法”类似(实际上,定义函数最常用的方法是作为某个对象的成员,这种函数被称为方法):

函数的类型和值
匿名函数、Lamda表达式与闭包
  • 我们不需要给每个函数命名,这时就可以使用匿名函数,如下:

scala> (num: Int) => num*2
res1: Int => Int = <function1>
  • 上面这种匿名函数的定义形式,我们经常称为“Lamda表达式”。“Lamda 表达式”的形式如下:

(参数) => 表达式 //如果参数只有一个,参数的圆括号可以省略
  • 我们可以直接把匿名函数存放到变量中,下面是在Scala解释器中的执行过程:

scala> val myNumFunc: Int => Int = (num: Int) => num*2 //这行是我们输入的命令,把匿名函数定义成一个值,赋值给myNumFunc变量
myNumFunc: Int => Int = <function1> //这行是执行结果
scala> println(myNumFunc(3)) //myNumFunc函数调用的时候,需要给出参数的值,这里传入3,得到乘法结果是6
6
  • 实际上,Scala具有类型推断机制,可以自动推断变量类型,比如下面两条语句都是可以的:

scala> val number: Int = 7
number: Int = 7
scala> val number = 7
number: Int = 7
  • 所以,上面的定义中,我们可以myNumFunc的类型声明,也就是去掉 “Int=>Int”,在Scala解释器中的执行过程如下:

scala> val myNumFunc = (num: Int) => num*2
myNumFunc: Int => Int = <function1>
scala>  println(myNumFunc(36))
72
  • 下面我们尝试一下,省略num的类型声明,但是,给出myNumFunc的类型 声明,在Scala解释器中的执行过程如下:

scala> val myNumFunc: Int => Int = (num) => num*2
myNumFunc: Int => Int = <function1>
  • 不会报错,因为,给出了myNumFunc的类型为“Int=>Int”以后,解释器可 以推断出num类型为Int类型。

  • 闭包是一个函数,一种比较特殊的函数,它和普通的函数有很大区别

  • 普通函数:

scala> var more = 1
more: Int = 1
scala> val addMore = (x: Int) => x > 0
addMore: Int => Boolean = <function1>
scala> addMore(10)
res11: Boolean = true
  • 闭包:

scala> var more = 1
more: Int = 1
scala> val addMore = (x: Int) => x + more
addMore: Int => Int = <function1>
scala> addMore(10)
res5: Int = 11
scala> more = 9
more: Int = 9
scala> addMore(10)
res10: Int = 19
  • 每次addMore函数被调用时都会创建 一个新闭包

  • 每个闭包都会访问闭包创建时活跃的 more变量

占位符语法
  • 为了让函数字面量更加简洁,我们可以使用下划线作为一个或多个参数的占 位符,只要每个参数在函数字面量内仅出现一次。

scala> val numList = List(-3,-5,1,6,9)
numList: List[Int] = List(-3, -5, 1, 6, 9)
scala> numList.filter(x => x > 0)
res0: List[Int] = List(1, 6, 9)
scala>  numList.filter(_ > 0)
res1: List[Int] = List(1, 6, 9)
  • 从上面运行结果可以看出,下面两个函数字面量是等价的。

x => x > 0
_ > 0
  • 有时你把下划线当作参数的占位符时,编译器有可能没有足够的信息推断缺 失的参数类型。例如,假设你只是写_ + _:

scala> val f = _ + _
<console>:7: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
      val f = _ + _
              ^
<console>:7: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
      val f = _ + _
                  ^
  • 这种情况下,你可以运用 冒号指定类型,如下:

scala> val f = (_: Int) + (_: Int)
f: (Int, Int) => Int = <function2>
scala> f(5,8)
res2: Int = 13
  • 请留心 _ + _将扩展成带两个参数的函数字面量。这也是仅当每个参数在函数 字面量中最多出现一次的情况下你才能运用 这种短格式的原由 。多个下划线 指代多个参数,而不是单个参数的重复运用 。第一个下划线代表第一个参数, 第二个下划线代表第二个,第三个……,如此类推。

Scala_函数式编程基础的更多相关文章

  1. 大数据技术之_16_Scala学习_04_函数式编程-基础+面向对象编程-基础

    第五章 函数式编程-基础5.1 函数式编程内容说明5.1.1 函数式编程内容5.1.2 函数式编程授课顺序5.2 函数式编程介绍5.2.1 几个概念的说明5.2.2 方法.函数.函数式编程和面向对象编 ...

  2. javascript函数式编程基础随笔

    JavaScript 作为一种典型的多范式编程语言,这两年随着React\vue的火热,函数式编程的概念也开始流行起来,lodashJS.folktale等多种开源库都使用了函数式的特性. 一.认识函 ...

  3. Scala 中的函数式编程基础(三)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  4. Scala 中的函数式编程基础(一)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  5. 3分钟看完Java 8——史上最强Java 8新特性总结之第一篇 函数式编程基础

    目录 · 行为参数化 · Lambda表达式 · 概况 · 函数式接口 · 类型推断 · 使用外层变量 · 方法引用 · 复合Lambda表达式 行为参数化 1. 理解函数式编程要先理解行为参数化. ...

  6. Scala 中的函数式编程基础(二)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  7. 5. Scala函数式编程的基础

    5.1 函数式编程内容及介绍顺序说明 5.1.1 函数式编程内容 -函数式编程基础 函数定义/声明 函数运行机制 递归(难点,[最短路径,邮差问题,迷宫问题,回溯]) 过程 惰性函数和异常 -函数式编 ...

  8. 让JavaScript回归函数式编程的本质

    JavaScript是一门被误会最深的语言,这话一点不假,我们看下它的发展历史. 1995年,Netscape要推向市场,需要一门脚本语言来配套它.是使用一门已有的语言,还是发明一门新的语言,这也不是 ...

  9. JavaScript中函数式编程中文翻译

    JavaScript 中的函数式编程 原著由 Dan Mantyla 编写 近几年来,随着 Haskell.Scala.Clojure 等学院派原生支持函数式编程的偏门语言越来越受到关注,同时主流的 ...

随机推荐

  1. PAT 甲级 1019 General Palindromic Number(20)(测试点分析)

    1019 General Palindromic Number(20 分) A number that will be the same when it is written forwards or ...

  2. ParseCrontab类,解析时间规则

    <?php /** * Created by PhpStorm. * User: ClownFish 187231450@qq.com * Date: 14-12-27 * Time: 上午11 ...

  3. Spring 属性注入(一)JavaBean 内省机制在 BeanWrapper 中的应用

    Spring 属性注入(一)JavaBean 内省机制在 BeanWrapper 中的应用 Spring 系列目录(https://www.cnblogs.com/binarylei/p/101174 ...

  4. mapreduce的输入格式 --- InputFormat

    InputFormat 接口决定了mapreduce如何切分输入文件. InputFormat 由getspilit和createRecordReader组成,getspilit主要是标记分片的初始位 ...

  5. cocos jsb工程转html 工程

    1 CCBoot.js prepare方法:注掉下面这行,先加载moduleConfig中的脚本后加载user脚本 //newJsList = newJsList.concat(jsList); // ...

  6. javase高级技术 - 泛型

    在写案例之前,先简单回顾下泛型的知识 我们知道,java属于强变量语言,使用变量之前要定义,并且定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 所谓“泛型”,就是“宽泛的数据类 ...

  7. Tomcat新问题 还没有解决:the apr based apache tomcat native librariy which allows optional perf...........

     问题信息详细: 2012-5-18 18:41:54 org.apache.catalina.core.AprLifecycleListener init 信息: The APR based Apa ...

  8. ListView动态改变每一项的高度。

    ListView中每一项的高度默认是相同的,除非超过其预定高度值,否则需要动点手脚. VariableSizedListView 继承 ListView然后重写protected override v ...

  9. Jvm(jdk8)源码分析1-java命令启动流程详解

    JDK8加载源码分析 1.概述 现在大多数互联网公司都是使用java技术体系搭建自己的系统,所以对java开发工程师以及java系统架构师的需求非常的多,虽然普遍的要求都是需要熟悉各种java开发框架 ...

  10. 通用Mapper

    原理是:拦截器 1.假设:使用MyBatis只需要定义Mapper接口,无需编写Mapper.xml文件 如果实现无需编写Mapper.xml文件,我们必须要实现动态拼接SQL 如何实现动态拼接SQL ...