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 *=_ }