Scala快速入门-9-高阶函数

简介: 作为值的函数创建匿名函数带函数参数的函数闭包柯里化

知识点


  • 作为值的函数
  • 创建匿名函数
  • 带函数参数的函数
  • 闭包
  • 柯里化

函数


  • 在Scala中,函数是“头等公民”,可以在变量中存放函数
scala> def fun(msg: String) {println(msg)}
fun: (msg: String)Unit
scala> val f = fun
<console>:8: error: missing arguments for method fun;
follow this method with `_' if you want to treat it as a partially applied function
       val f = fun
               ^
scala> val f = fun _
f: String => Unit = <function1>
scala> f("Yezhiwei")
Yezhiwei

函数后面的 _ 意味着指的是这个函数

  • 作为参数传递给另一个函数
scala> Array("Hello", "Scala").map(f)
Hello
Scala
res2: Array[Unit] = Array((), ())

map方法接受一个函数参数,将它应用到数组中的所有值,然后返回结果数据

  • 在Scala中,不需要给每一个函数命名,匿名函数
1. scala> (x: Double) => 3 * x
2. res3: Double => Double = <function1>
• 在Scala中,可以将上面的函数放到变量中
3. scala> val triple = (x: Double) => 3 * x
4. triple: Double => Double = <function1>
5. 
6. 与def一样
7. def triple = (x: Double) = 3 * x
  • 可以将匿名函数直接传递给另一个函数
scala> Array(3.14, 1.42).map((x: Double) => 3 * x)
res4: Array[Double] = Array(9.42, 4.26)
  • 带函数参数的函数,如实现接受另一个Double并且返回Double的函数
scala> def fun(f: (Double) => Double) = f(0.25)
fun: (f: Double => Double)Double
scala> import scala.math._
import scala.math._
scala> fun(ceil _)
res12: Double = 1.0
scala> fun(sqrt _)
res13: Double = 0.5
///////////
scala> def mulBy(factor: Double) = (x: Double) => factor * x
mulBy: (factor: Double)Double => Double
scala> val q = mulBy(5)
q: Double => Double = <function1>
scala> q(20)
res14: Double = 100.0
// val q = mulBy(5) 相当于 val q = (x: Double) => 5 * x
  • 将一个匿名函数传递给另一个函数或方法时,Scala会尽可能推断出类型信息
scala> def fun(f: (Double) => Double) = f(0.25)
fun: (f: Double => Double)Double
scala> fun((x: Double) => 3 * x)
res16: Double = 0.75
// 由于fun方法知道会传入一个类型为(Double) => Double的函数,可以简单地写成
scala> fun((x) => 3 * x)
res17: Double = 0.75
// 对于只有一个参数的函数,可以省略参数外围的()
scala> fun(x => 3 * x)
res18: Double = 0.75
// 如果参数在=>右侧只出现一次,可以用_替换掉它
scala> fun(3 * _)
res19: Double = 0.75
  • 常用的高阶函数
scala> (1 to 9).map(0.1 * _)
res20: scala.collection.immutable.IndexedSeq[Double] = Vector(0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9)
/////
scala> (1 to 9).map("*" * _).foreach(println _)
*
**
***
****
*****
******
*******
********
*********
/////
scala> (1 to 9).filter(_ % 2 == 0)
res23: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8)
///// 相当于1 * 2 * 3 * 4 ... * 9
scala> (1 to 9).reduceLeft(_ * _)
res0: Int = 362880
...

闭包


  • 闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
  • 闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。
scala> def mulBy(factor: Double) = (x: Double) => factor * x
mulBy: (factor: Double)Double => Double
scala> val triple = mulBy(3)
triple: Double => Double = <function1>
scala> val half = mulBy(0.5)
half: Double => Double = <function1>
scala> println(triple(14) + " " + half(14))
42.0 7.0

mulBy的首次调用将参数变量factor设置为3,该变量在(x: Double) => factor * x函数的函数体内被引用,该函数被存入triple。

接下来,mulBy再次被调用,这次factor设置为0.5,该变量在(x: Double) => factor * x函数的函数体被引用,该函数被存入half。

每一个返回的函数都有自己的factor设置,这样一个函数被称做闭包,闭包由代码和代码用到的任何非局变量定义构成。

柯里化


  • 柯里化指的是将原来接收两个参数的函数变成新的接收一个参数的函数的过程。新的函数返回一个以原有第二个参数作为参数的函数
scala> def mul(x: Int, y: Int) = x * y
mul: (x: Int, y: Int)Int
scala> def mulOne(x: Int) = (y: Int) => x * y
mulOne: (x: Int)Int => Int
scala> mulOne(6)(7)
res1: Int = 42
// mulOne(6)的结果是函数(y: Int) => 6 * y,崦这个函数又被应用到7,因此得到42。


相关文章
|
5月前
|
Scala 开发者
Scala中的模式匹配与高阶函数:探索强大的编程范式
【7月更文挑战第11天】Scala中的模式匹配和高阶函数是两种极其强大的特性,它们不仅提升了代码的表达力和可读性,还使得开发者能够编写出更加灵活和可重用的解决方案。通过
|
6月前
|
Java 大数据 Scala
Scala快速入门--Scala环境搭建【Windows10】图解
Scala快速入门--Scala环境搭建【Windows10】图解
85 0
|
7月前
|
SQL 分布式计算 编译器
Scala:高阶函数、隐式转换(四)
Scala:高阶函数、隐式转换(四)
59 0
|
Scala
172 Scala 高阶函数例子
172 Scala 高阶函数例子
31 0
|
算法 Scala
171 Scala 高阶函数
171 Scala 高阶函数
43 0
|
分布式计算 前端开发 Java
Scala高阶函数与akka 2
Scala高阶函数与akka
68 0
|
算法 Java 编译器
Scala高阶函数与akka 1
Scala高阶函数与akka
70 0
|
消息中间件 Java 大数据
Scala快速入门
Scala快速入门
109 0
Scala快速入门-11-常用集合操作
所有的集合都扩展自Iterable特质 集合有三大类,分别为序列、集和映射 几乎所有集合类,Scala都同时提供了可变和不可变的版本 Scala列表要么是空的,要么拥有一头一尾,其中尾部本身又是一个表列 集是无先后次序的集合 用LinkedHashSet来保留插入顺序,或用SortedSet来按顺序进行迭代 +将元素添加到无先后次序的集合中;+:和:+向前或向后追加到序列;++将两个集合串接在一起;-和--移除元素 映射、折叠和拉链操作是很有用的技巧,用来将函数和操作应用到集合中的元素
|
安全 Java 编译器
Scala快速入门-10-模式匹配与样例类
mathch表达式是一个更好的switch,不会有穿透到下一个分支的问题 如果没有模式能够匹配,会抛出MatchError,可以用case _ 模式来避免,相当于Java中的default 模式可以包含一个随意定义的条件,称做守卫 可以匹配数组、列表、元组等模式,然后将匹配到不同部分绑定到变量 样例类及密封类的模式匹配 用Option来存放可能存在也可能不存在的值,比null更安全