1. 程式人生 > >Scala 函式與匿名函式

Scala 函式與匿名函式

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
}

綜合性栗子: 求 baf(x)

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  


    }