一、函数作为参数
highOrderFunc是一个高阶函数,因为它可以接收一个函数作为参数
object PartialFunctionDemo { def main(args: Array[String]): Unit = { val add = (d: Double) => d + 1 val res = highOrderFunc(add, 5) println(res) } def highOrderFunc(f: Double => Double, p: Double) = f(p) }
二、函数作为返回值
函数f接收一个参数n,返回一个函数(x: Double) => n - x
f(5)(8),f(5)的返回值是一个函数,(8)是上一步返回函数的参数
def main(args: Array[String]): Unit = { val f = (n: Double) => (x: Double) => n - x val res = f(5)(8) println(res) // -3 }
三、闭包 closure
闭包就是一个函数和与其相关的引用环境组合的一个整体。如下代码中mkSuffix函数的返回值就是一个函数,这个函数引用到了外部的suffix,它们共同组成一个闭包。好处是变量suffix一次传入,后面可以多次使用。
def main(args: Array[String]): Unit = { val suffix = mkSuffix(".jpg") println(suffix("cat")) // cat.jpg println(suffix("dog.jpg")) // dog.jpg } def mkSuffix(suffix: String) = { (fileName: String) => if (fileName.endsWith(suffix)) fileName else fileName + suffix }
四、函数科里化
如下代码,求1到5的乘积。函数科里化可以将需要多步完成的一个函数,拆解成每步完成一件事的多个函数。这样做的好处是拆解出更加细粒度的函数,得到共用的中间结果,类似于代码封装、数仓分层的思想。
object PartialFunctionDemo { def main(args: Array[String]): Unit = { val res1 = curry01(1)(2)(3)(4)(5) println(res1) // 120 val temp = curry2(1)(2)(3) val res2 = temp(4)(5) println(temp) // <function1> println(res2) // 120 } def curry01(a: Int)(b: Int)(c: Int)(d: Int)(e: Int) = a * curry02(b)(c)(d)(e) def curry02(b: Int)(c: Int)(d: Int)(e: Int) = b * curry03(c)(d)(e) def curry03(c: Int)(d: Int)(e: Int) = c * curry04(d)(e) def curry04(d: Int)(e: Int) = d * curry05(e) def curry05(e: Int) = e def curry2(a: Int) = { b: Int => c: Int => d: Int => e: Int => a * b * c * d * e } }
五、控制抽象
函数test的参数是一个函数f,而且函数f既没有输入值也没有返回值,此时函数test就叫控制抽象
object ScalaDemo { def main(args: Array[String]): Unit = { test(f _) } def test(f: () => Unit) = { f() } def f = { println("hello") println("scala") } }
对于控制抽象函数,可以作如下简写
object ScalaDemo { def main(args: Array[String]): Unit = { //传递参数函数f时,直接传递代码块。如果只有一行,可以用小括号 test{ println("hello") println("scala") } } //去掉入参的小括号,: 和 => 之间有空格 def test(f: => Unit) = { //调用时也去掉小括号 f } }
利用控制抽象,实现一段循环
object ScalaDemo { def main(args: Array[String]): Unit = { var num = 10 until(num > 0) { num -= 1 println(num) } } def until(condition: => Boolean)(block: => Unit): Unit = { if (condition) { block //递归调用 until(condition)(block) } } }