Scala笔记:用函数字面量块调用高阶函数

这里会用到几个概念高阶函数、函数字面量、参数组

高阶函数

high-order function 函数的一种,简单来说它包含了一个函数类型的参数或者返回值。

所谓的高阶是跟一阶函数相比,深入一下:

  1. 一个或多个参数是函数,并返回一个值。
  2. 返回一个函数,但没有参数是函数。
  3. 上述两者叠加:一个或多个参数是函数,并返回一个函数。

示例:

1
2
3
4
5
6
7
8
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的函数字面量定义:

1
val reverse = (s:String) => s.reverse

(s:String) => s.reverse定义了一个有类型的输入参数(s:String)和函数体(s.reverse)。

定义为高阶函数调用的一部分:

1
stringSafeOp("Ready", (s:String) => s.reverse)

由于已经定义了参数f的类型String => String,可以从函数字面量中删除显示类型,交由编译器自动推导其类型。

1
stringSafeOp("Ready", s => s.reverse)

占位符语法

Placeholder syntax是函数字面量的一种缩写形式,将命名参数替换为通配符(_)。

使用条件: > 函数的显示类型在字面量之外指定 > > 参数最多只使用一次

前面的例子正好符合条件:

stringSafeOp定义中指定了字面量的类型(字面量之外) String => String

参数s只使用一次 s.reverse

1
stringSafeOp("Ready", _.reverse)

参数组

parameter groups 函数的参数列表的另一种形式:分解并使用小括号分隔。

stringSafeOp的参数组表示:

1
2
3
4
def stringSafeOp(s: String)(f: String => String) = {
    if ( s != null) f(s) else s
}
//stringSafeOp: (s: String)(f: String => String)String

用函数字面量块调用高阶函数

组合上面的特性,就有了用函数字面量块调用高阶函数

1
val newStringSafeOp = stringSafeOp("Ready"){_.reverse}

进阶

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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方法对方法调用进行时间记录,对目标代码没有侵入性。

Comments

comments powered by Disqus