Scala函数值
函数值的使用
- 可以在函数里创建函数
- 将函数赋给引用
- 当作参数传给其他函数
- 作为函数的返回值
单参函数值
def totalResultOverRange(number: Int, codeBlock: Int => Int) : Int = {
var result = 0
for (i <- 1 to number) {
result += codeBlock(i)
}
result
}
println(totalResultOverRange(11, i => i))
println(totalResultOverRange(11, i => if (i%2 == 0)1 else 0))
println(totalResultOverRange(11, i => if (i%2 != 0)1 else 0))
多参函数值
def inject(arr: Array[Int], initial: Int, operation: (Int, Int) => Int) : Int = {
var carryOver = initial
arr.foreach( element => carryOver = operation(carryOver, element) )
carryOver
}
val array = Array(2, 3, 5, 1, 6, 4)
val sum = inject(array, 0, (carryOver, elem) => carryOver + elem)
val max = inject(array, Integer.MIN_VALUE, (carryOver, elem) => Math.max(carryOver, elem) )
operation: (Int, Int) => Int : Int
表示函数名、参数类型和返回值类型(函数值的申明
)
这里的operation函数中有一个赋值操作,赋值对象为carryOver
Curry化
curry化可以把函数从接收多个参数转换成接收多个参数列表。
def foo(a: Int, b: Int, c: Int) {}
可以改写成def foo(a: Int)(b: Int)(c: Int) {}
形式。
对应的调用方法为foo(1)(2)(3)、foo(1){2}{3},甚至foo{1}{2}{3}。
def inject(arr: Array[Int], initial: Int)(operation: (Int, Int) => Int) : Int = {
var carryOver = initial
arr.foreach(element => carryOver = operation(carryOver, element))
carryOver
}
为函数值创建引用
- 函数值的引用
val calculator = { input : Int => println("calc with " + input); input }
input : Int
表示函数值的参数名和参数类型(函数值的实现
)
- 定义函数
def calculator(input: Int) = { println("calc with " + input); input }
位置参数简化
- 简化一个参数
val negativeNumberExists = arr.exists { _ < 0 }
- 简化两个参数
(0 /: arr) { (sum, elem) => sum + elem }
(0 /: arr) { _+_}
def max2(a: Int, b: Int) : Int = if (a> b)a else b
(Integer.MIN_VALUE /: arr) { (large, elem) => max2(large, elem) }
(Integer.MIN_VALUE /: arr) { max2(_, _) }
第一个出现的_表示的是一个函数调用过程中持续存在的值,第二个表示数组元素
- 简化整个参数列表
max = (Integer.MIN_VALUE /: arr) { max2 _ }
- 简化为零
max = (Integer.MIN_VALUE /: arr) { max2 }
借贷模式
import java.io._
def writeToFile(fileName: String)(codeBlock : PrintWriter => Unit) = {
val writer = new PrintWriter(new File(fileName))//借
try {
codeBlock(writer)//使用
} finally {
writer.close()//还
}
}
writeToFile("output.txt") { writer => writer write "hello from Scala" }
偏应用函数
一个函数如果只传递几个参数其它的留待后面填写,就得到了一个偏应用函数。使用_
指定不绑定的参数
def log(date: Date, message: String)
val logWithDateBound = log(new Date, _ : String)
闭包
如果代码块包含未绑定的参数就称为闭包,调用函数之前必须绑定这些参数。
- 函数值引用绑定
def loopThrough(number: Int)(closure: Int => Unit) {
for (i <- 1 to number) { closure(i) }
}
var result = 0
val addIt = { value:Int => result += value }
loopThrough(10) { addIt }
- 匿名函数绑定
var product = 1
loopThrough(5) { product *=_ }