文章目录
- 作为值的函数
- 匿名函数
- 带函数参数的函数
- 参数类型推断
- 一些有用的高阶函数
- 闭包
- SAM转换
- 柯里化
作为值的函数
import scala.math._
val num = 3.45
val fun = ceil _
println(fun(3.45))
- ceil是math这个包对象的方法,如果有来自类的方法,将其变成函数的方式
scala> val f = (_:String).charAt(_:Int)
f: (String, Int) => Char = <function2>
scala> val f1:(String,Int)=>Char = _.charAt(_)
f1: (String, Int) => Char = <function2>
scala> val add : (Int,Int)=>Int = (x,y)=>x+y
add: (Int, Int) => Int = <function2>
- 可以对函数
调用
、传递(存放在变量中或作为参数传递给另一个函数)
scala> fun(3.13)
res10: Double = 4.0
scala> Array(3.1,3.4,5.7).map(fun)
res11: Array[Double] = Array(4.0, 4.0, 6.0)
匿名函数
- 函数不一定有名字,就像数字也不一定有名字
- 以def定义的都是方法,不是函数
- 结合第二章的内容
- 函数名的后面有时候是冒号有时候是等号。如果右侧显式指明函数的类型就用冒号,如果不显式指明函数的类型就用等号,函数类型可以通过自动推断得到
scala> (x:Double) => 3*x
res12: Double => Double = <function1>
scala> val triple=(x:Double) => 3*x
triple: Double => Double = <function1>
scala> val triple1:(Double)=>Double = 3*_
triple1: Double => Double = <function1>
scala> val triple1:(Double)=>Double = x => 3*x
triple1: Double => Double = <function1>
scala> Array(3.1,3.4,5.7).map(triple1)
res13: Array[Double] = Array(9.3, 10.2, 17.1)
scala> Array(3.1,3.4,5.7).map{triple1}
res14: Array[Double] = Array(9.3, 10.2, 17.1)
带函数参数的函数
- 函数作为参数
- 高阶函数:函数作为参数或返回值
- 如下示例
def valueAtQuator(f:(Double)=>Double):Double = f(0.25)
def mulBy(factor:Double):Double=>Double = {(x:Double)=>factor*x}
参数类型推断
- scala会自动类型推断
- 给出_的类型有助于将方法变为函数
scala> valueAtQuator((x:Double) => 3*x)
res19: Double = 0.75
scala> valueAtQuator((x) => 3*x)
res20: Double = 0.75
scala> valueAtQuator(x => 3*x)
res21: Double = 0.75
scala> valueAtQuator(3*_)
res22: Double = 0.75
scala> (_:String).substring(_:Int,_:Int)
res0: (String, Int, Int) => String = <function3>
一些有用的高阶函数
- 练习scala集合库中的一些接受函数参数的方法
- foreach 将函数应用到每个元素,不返回值
- filter交出所有满足条件的元素
- reduceLeft
scala> (1 to 9).map("*"*_).foreach(println)
*
**
***
****
*****
******
*******
********
*********
scala> (1 to 9).filter( _ % 2 ==0)
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8)
scala> (1 to 9).map(_.toString).reduceLeft( (x,y) => (s"f(${x},${y})"))
res8: String = f(f(f(f(f(f(f(f(1,2),3),4),5),6),7),8),9)
scala> (1 to 9).map(_.toString).reduceRight( (x,y) => (s"f(${x},${y})"))
res9: String = f(1,f(2,f(3,f(4,f(5,f(6,f(7,f(8,9))))))))
scala> Array(4,1,2,6).sortWith(_<_)
res11: Array[Int] = Array(1, 2, 4, 6)
闭包
- 闭包由代码和代码用到的任何非局部变量定义构成
- 下面的示例中,每一个函数都有自己的factor设置
def mulBy(factor:Double):Double=>Double = {(x:Double)=>factor*x}
scala> def triple = mulBy(3)
triple: Double => Double
scala> def hale = mulBy(0.5)
hale: Double => Double
SAM转换
- Single Abstract method 带有单个抽象方法
- scala函数到java SAM接口转换只对函数字面量有效
柯里化
- 将原来接受两个参数的函数变成新的接受一个参数的函数的过程,新的函数返回一个以原有第二个参数作为参数的函数。
scala> val mul = (x:Int,y:Int)=>x*y
mul: (Int, Int) => Int = <function2>
scala> val mulOneATime =(x:Int)=>((y:Int)=>x*y)
mulOneATime: Int => (Int => Int) = <function1>
scala> mulOneATime(6)(7)
res12: Int = 42
scala> def mulOneATime1 (x:Int)(y:Int)=x*y
mulOneATime1: (x: Int)(y: Int)Int
scala> val mulOneATime2 = (x:Int) => (y:Int)=>x*y
mulOneATime2: Int => (Int => Int) = <function1>
- 柯里化把某个函数参数单独提出来,以提供更多用于类型推断的信息
- _.equalsIgnoreCase(_)是一个经过柯里化的参数的形式传递
scala> val a = Array("hello","world")
a: Array[String] = Array(hello, world)
scala> val b = Array("Hello","world")
b: Array[String] = Array(Hello, world)
scala> a.corresponds(b)(_.equalsIgnoreCase(_))
res13: Boolean = true
def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Boolean = {
val i = this.iterator
val j = that.iterator
while (i.hasNext && j.hasNext)
if (!p(i.next(), j.next()))
return false
!i.hasNext && !j.hasNext
}