Scala笔记:用函数字面量块调用高阶函数
这里会用到几个概念高阶函数、函数字面量、参数组
高阶函数
high-order function 函数的一种,简单来说它包含了一个函数类型的参数或者返回值。
所谓的高阶是跟一阶函数相比,深入一下:
- 一个或多个参数是函数,并返回一个值。
- 返回一个函数,但没有参数是函数。
- 上述两者叠加:一个或多个参数是函数,并返回一个函数。
示例:
def stringSafeOp(s: String, f: String => String) = {
if ( s != null) f(s) else s
}
//stringSafeOp: (s: String, f: String => String)String
def reverse(s: String) = s.reverse
//reverse: (s: String)String
stringSafeOp("Ready", reverse)
//res86: String = ydaeR
函数字面量
function literal,其他名字:匿名函数、Lambda表达式等。 函数字面量可以存储在函数值和变量中,或者也可以定义为高阶函数调用的一部分。在任何接受函数类型的地方都可以使用函数字面量。
reverse的函数字面量定义:
val reverse = (s:String) => s.reverse
(s:String) => s.reverse
定义了一个有类型的输入参数(s:String)和函数体(s.reverse)。
定义为高阶函数调用的一部分:
stringSafeOp("Ready", (s:String) => s.reverse)
由于已经定义了参数f的类型String => String
,可以从函数字面量中删除显示类型,交由编译器自动推导其类型。
stringSafeOp("Ready", s => s.reverse)
占位符语法
Placeholder syntax是函数字面量的一种缩写形式,将命名参数替换为通配符(_)。
使用条件:
函数的显示类型在字面量之外指定
参数最多只使用一次
前面的例子正好符合条件:
stringSafeOp定义中指定了字面量的类型(字面量之外)
String => String
参数s只使用一次
s.reverse
stringSafeOp("Ready", _.reverse)
参数组
parameter groups 函数的参数列表的另一种形式:分解并使用小括号分隔。
stringSafeOp的参数组表示:
def stringSafeOp(s: String)(f: String => String) = {
if ( s != null) f(s) else s
}
//stringSafeOp: (s: String)(f: String => String)String
用函数字面量块调用高阶函数
组合上面的特性,就有了用函数字面量块调用高阶函数。
val newStringSafeOp = stringSafeOp("Ready"){_.reverse}
进阶
def timer[A](f: => A) = {
def now = System.currentTimeMillis
val start = now; val a = f; val end = now
println(s"Executed int ${end - start} ms")
a
}
val veryRandomAmount = timer {
util.Random.setSeed(System.currentTimeMillis)
for (i <- 1 to 100000) util.Random.nextDouble
util.Random.nextDouble
}
timer方法对方法调用进行时间记录,对目标代码没有侵入性。