Scala 函式與匿名函式
阿新 • • 發佈:2018-12-25
1 函式是第一等公民
Scala語言支援:
- 把函式作為實參傳遞給另外一個函式
- 把函式作為返回值
- 把函式賦值給變數
- 把函式儲存在資料結構裡
在Scala中,函式就像普通變數一樣,同樣也具有函式的型別。
函式型別格式:A => B
表示一個接受型別A的引數,並返回型別B的引數
eg: Int => String 是把整型對映為字串的函式型別
2.高階函式
用函式作為形參或返回值的函式,稱為高階函式
def operate(f:(Int,Int) => Int){
f(4,3)
}
def greeting() =(name:String) => {"hello" + "" + name}
3.匿名函式
匿名函式(Anonymous Function),也就是函式常量,也稱為函式文字量(Function Literal)。
在Scala 中,匿名函式的定義格式為
(形參列表)=>{函式體}
eg:
object example {
def operate(x:Int)=x*x //> operate: (x: Int)Int
operate(2) //> res0: Int = 4
def add(x:Int,y:Int)=x+y //> add: (x: Int, y: Int)Int
add(1,2) //> res1: Int = 3
}
4.柯里化函式(Currried Function)
柯里化函式就是把具有多個引數的函式轉換為一條函式鏈,每個節點上是單一引數。
eg:以下兩個add函式定義是等價的
def add(x : Int, y: Int) = x + y
def add(x: Int)(y: Int)= x + y //Scala裡柯里化的語法
def curriedAdd(a: Int)(b: Int) = a + b
curriedAdd(2)(2) //a=2,b=2,a+b=4
val addOne - curriedAdd(1 )_ //Int=>Int 萬用字元_,a=1,b是變數
addOne(2) //a=1,b=2,a+b=3
5.遞迴函式(Recursive Function)
遞迴函式在函數語言程式設計是實現迴圈的以一種技術.
eg: 計算n!
def factorial(n:Int): Int =
if(n<=0) 1 //直接返回1
else n*factorial(n-1)
//缺點:堆疊進行函式呼叫的時候,遞迴層數越深就容易導致堆疊溢位
優化方案:尾遞迴函式(Tail Recursive Function)
所有遞迴形式的呼叫都出現在函式的末尾,當編譯器檢測到一個函式呼叫是尾遞迴的時候,它就覆蓋當前的活動記錄而不是去棧中去建立一個新的。**
@annotation.tailrec
def factorial(n: Int,m:Int):Int =
if(n <=0) m
else factorial(n-1,m*n) //> factorial: (n: Int, m: Int)Int
factorial(5, 1) //> res2: Int = 120
}
綜合性栗子: 求
object Sumfunction{
def sum(f: Int => Int)(a: Int)(b: Int): Int= {
@annotation.tailrec
def loop(n: Int,acc: Int):Int = {
if(n > b){
println(s"n=${n},acc=${acc}")
acc
} else {
println(s"n=${n},acc=${acc}")
loop(n + 1,acc + f(n))
}
}
loop(a,0)
} // sum: (f: Int => Int)(a: Int)(b: Int)Int
--------------------------------------------------------
sum(x=>x*x)(1)(5) **** val sumSquare = sum(x=>x*x)_
sumSquare(1)(5)
-----------------------------------------------------------
sum(x=>x)(1)(5) // n=1,acc=0
// n=2,acc=1
//|n=3,acc=3
// n=4,acc=6
// n=5,acc=10
// n=6,acc=15
//res0: Int = 15
sum(x=>x*x)(1)(5) //> n=1,acc=0
//| n=2,acc=1
//| n=3,acc=5
//| n=4,acc=14
//| n=5,acc=30
//| n=6,acc=55
//| res1: Int = 55
sum(x=>x*x*x)(1)(5) //> n=1,acc=0
//| n=2,acc=1
//| n=3,acc=9
//| n=4,acc=36
//| n=5,acc=100
//| n=6,acc=225
//| res2: Int = 225
val sumSquare = sum(x =>x*x)_
sumSquare(1)(5)
//> n=1,acc=0
//| n=2,acc=1
//| n=3,acc=5
//| n=4,acc=14
//| n=5,acc=30
//| n=6,acc=55
//| res1: Int = 55
}