Scala--高階函數

1、做爲值的函數

  import scala.math._

  val num  = 3.14
  val func = ceil _ // _意味着確實指的是這個函數,而不是忘記了傳參數 ,func是一個函數變量,內容保存的是個函數

  val v = func(num)
  println(v)
  val arr = Array(1.0,3.14,4).map(func)  //將函數func傳遞給map方法,將他應用到數組中的全部值,而後返回結果數組
  for(i<- arr) print(i+" ")

結果:數組

4.0
1.0 4.0 4.0 

 

2、匿名函數

  val func = (x:Double) => x*3 //匿名函數
 val arr1 = Array(2.0,4,6).map((x:Double)=> x*3) //匿名函數 val arr2 = Array(2.0,4,6).map{(x:Double)=> x*3} //匿名函數,能夠將函數用{}括起來 val arr3 = Array(2.0,4,6) map{(x:Double)=> x*3} //匿名函數,中置表示法,能夠不用句號 for(i <- arr1) print(i+" ")

 

3、帶函數參數的函數

  import scala.math._
  def valueAtFunc(f: (Double) => Double) = { // f: (Double) => Double 定義函數參數爲 double,返回值爲double
    f(0.25) //調用函數的參數爲 2.0
  }

  println(valueAtFunc(ceil _))  //將函數傳遞個 函數valueAtFunc
  println(valueAtFunc(sqrt _))

結果:閉包

1.0
0.5

 

4、參數(類型)推斷

  import scala.math._
    def valueAtFunc(f: (Double) => Double) = { // f: (Double) => Double 定義函數參數爲 double,返回值爲double
      f(0.25) //調用函數的參數爲 2.0
    }

    println(valueAtFunc(ceil _))  //將函數傳遞個 函數valueAtFunc
    println(valueAtFunc(sqrt _))

  valueAtFunc((x:Double) => x*3 ) //匿名函數,指定類型
  valueAtFunc((x)=>x*3)      //匿名函數,已知參數類型
  valueAtFunc(x=>x*3)        //匿名函數,已知參數類型,去掉括號
  valueAtFunc(_*3)           //使用_替換 x

  val f1 = 3 * _   //錯誤,沒指定類型
  val f2 = 3 *(_:Double)  //ok
  val f3:(Double)=>Double = 3 * _ // ok 指定了f3類型

匿名函數簡寫:函數

valueAtFunc((x:Double) => x*3 ) //匿名函數,指定類型
valueAtFunc((x)=>x*3) //匿名函數,已知參數類型
valueAtFunc(x=>x*3) //匿名函數,已知參數類型,去掉括號
valueAtFunc(_*3) //使用_替換 x

 

5、一些有用的高階函數

map這個方法將一個函數應用到某個集合的全部元素並返回結果spa

foreach將函數應用到每一個元素,並不返回結果scala

(0 to 9).map("*" * _).foreach(println(_))

結果:code

*
**
***
****
*****
******
*******
********
*********

filter輸出全部匹配某個特定條件的元素blog

(0 to 9).filter(_ % 2 == 0).foreach(println(_))

結果:排序

0
2
4
6
8

reduceLeft方法接收一個二元函數,從左到右遍歷元素it

println((0 to 9).reduceLeft(_ + _))   // 至關於  (...((((0+1) + 2) + 3) + 4) ...+ 9)

結果io

45

sortWith方法二元排序

"I am a bad guy".split(" ").sortWith(_.length<_.length).foreach(println(_))

結果:

I
a
am
bad
guy

 

6、閉包

閉包由代碼和代碼用到的非局部變量定義構成

 

7、SAM轉換

Single Abstract Method

 

 

8、柯里化

Currying,指的是將本來接收兩個參數的函數變成新的接收一個參數的函數的過程。

  def mul(x:Int, y:Int) = x * y  //接收兩個參數的函數

  def mulOneAtATime(x:Int) = (y:Int)=> x * y  //接收一個參數的函數,須要接收兩次參數
  def mulOneAtATime1(x:Int)(y:Int) = x * y //柯里化 簡寫
  println(mulOneAtATime(3)(4))
  println(mulOneAtATime1(3)(4))

 

柯里化用途:

傳遞一個參數調用函數,有助於對參數類型進行推斷,即類型推斷

  val a = Array("Hello","World")
  val b = Array("hello","world")

  a.corresponds(b)(_.equalsIgnoreCase(_))

Scaladoc說明

that是String類型的序列,因此第二個函數參數是(String, String) => Boolean,因此適用函數_.equalsIgnoreCase(_)傳遞兩個String類型參數的函數。

 

9、控制抽象

實現相似while條件控制,柯里化實現

  //until函數  相似於while
  def until(condition: => Boolean) (block: => Unit) { //不帶參數,沒有返回值的函數 block: => Unit
    if(condition){
      block
      until(condition)(block)
    }
  }

  var x:Int = 10
  until(x > 0){ //傳遞兩個函數體, 第一個函數體當作條件,第二個函數體當作計算塊
    x -= 1
    println(x)
  }

結果:

9
8
7
6
5
4
3
2
1
0

 

10、return表達式

  //until函數  相似於while
  def until(condition: => Boolean) (block: => Unit) { //不帶參數,沒有返回值的函數 block: => Unit
    if(condition){
      block
      until(condition)(block)
    }
  }

  var x:Int = 10
  until(x > 0){ //傳遞兩個函數體, 第一個函數體當作條件,第二個函數體當作計算塊
    x -= 1
    println(x)
  }

  def indexOf(str: String, ch:Char): Int ={
    var i = 0
    until( i!=str.length){
      if( str(i) == ch) return i      //return 返回給帶名函數,並不返回給匿名函數 {if(str(i) == ch) return i; i+=1}的until
      i+=1
    }
    return -1
  }
  println(indexOf("Hello", 'i'))

return在控制抽象中頗有用。

 

 

參考《快學Scala》

相關文章
相關標籤/搜索