@
函數可以作爲值進行傳遞
- 語法
var f = 函數名 _
- 如果明確了變量的數據類型,那麼下劃線可以省略
//函數正常的聲明與調用
def foo():Int={
println("foo...")
10
}
//將foo函數的執行結果賦值給res變量
//val res: Int = foo()
//println(res)
//函數作爲值進行傳遞 語法:在函數名稱的後面 + 空格 加下劃線
//注意:將foo函數作爲一個整體,賦值給f變量, f是函數類型 ()=>Int
//val f : () => Int = foo _
def f : () => Int = foo _
//這個時候,f就是一個函數,如果要想運行f函數的話,必須得加()
//println(f) //<function0>
//println("-----------------")
//println(f())
//var ff = foo //將函數執行結果賦值給ff
//var ff = foo _ //將函數本身作爲值賦給ff
//將函數本身作爲值賦給ff 如果明確了變量的類型,那麼空格和下劃線可以省略
//var ff:()=>Unit = foo
//println(ff)
函數可以作爲參數進行傳遞
- 通過匿名函數
- 擴展函數的功能
- 提高函數的靈活度
//函數可以作爲參數,進行傳遞(大多數情況都是通過匿名函數的形式)
//定義一個函數calculator,該函數接收一個函數類型的參數op,op定義了對兩個整數要進行什麼樣的操作
def calculator(a:Int,b:Int,op:(Int,Int)=>Int): Int ={
op(a,b)
}
//定義一個函數f1,完成兩個整數的加法運算
def op(a:Int,b:Int):Int={
a + b
}
//println(calculator(10,20,op))
println(calculator(50, 20, (a: Int, b: Int) => {
a - b
}))
println(calculator(50, 20, _ - _))
println(calculator(50, 20, _ + _))
*/
函數可以作爲返回值進行返回
- 函數的嵌套
- 函數鏈式調用,通過參數傳遞數據,在執行的過程中,函數始終佔據棧內存,容易導致內存溢出
//函數可以作爲返回值進行返回----函數的嵌套
def f1():()=>Unit ={
def f2(): Unit ={
println("f2函數被調用了")
}
//將f2作爲返回值返回給f1
f2 _
}
//ff就是f2
//var ff = f1()
//ff()
//f1()()
閉包
內層函數訪問外層函數的局部變量,會自動延長外層函數局部變量的生命週期,與內層函數形成一個閉合的效果,我們稱之爲閉包
/*
def f1(): (Int)=>Int ={
var a:Int = 10
def f2(b:Int): Int ={
a + b
}
f2 _
}
*/
//執行f1函數返回f2,將返回的f2賦值給ff變量
//val ff: Int => Int = f1()
//閉包:內存函數f2要訪問外層函數f1局部變量a,當外層函數f1執行結束之後,f1會釋放棧內存,但是會自動的延長f1函數的局部變量的生命週期,
// 和內層函數f2形成一個閉合的效果,我們將這種閉合的效果稱之爲閉包
//如果存在閉包,那麼編譯器會生成包含$anonfun$的字節碼文件
//閉包 = 外層函數的局部變量 + 內層函數
//調用ff函數,其實就是調用f2
//println(ff(20))
//也可以直接通過如下方式調用
//println(f1()(30))
println("-----------------------------------")
//以上代碼可以轉換爲如下代碼
/*
def f3() ={
var a:Int = 10
(b:Int) => a + b
}
f3()(30)
*/
柯里化
- 將一個參數列表中的多個參數,拆分爲多個參數列表
- 好處1:每一個參數列表表示函數清晰明確
- 好處2:簡化閉包代碼的編寫
//柯里化
//將一個函數的一個參數列表中的多個參數,拆分爲多個參數列表
//簡化閉包代碼的編寫
def f4()(b:Int):Int = {
var a:Int = 10
a + b
}
println(f4()(20))
//f4在執行的時候,其實會轉換爲以下結構
/*
def f4() ={
var a:Int = 10
(b:Int) => a + b
}
什麼是匿名函數
- 參數的類型可以省略,會根據形參進行自動的推導
- 類型省略之後,發現只有一個參數,則圓括號可以省略;其他情況:沒有參數和參數超過1的永遠不能省略圓括號。
- 匿名函數如果只有一行,則大括號也可以省略
- 如果參數只出現一次,則參數省略且後面參數可以用_代替