好程式設計師大資料學習路線分享高階函式

好程式設計師IT發表於2019-08-21

  好程式設計師大資料學習路線分享高階函式,我們通常將可以做為引數傳遞到方法中的表示式叫做函式

高階函式包含:作為值的函式、匿名函式、閉包、柯里化等等。

定義函式時格式:val 變數名 = (輸入引數型別和個數) => 函式實現和返回值型別和個數

“=”表示將函式賦給一個變數

“=>”左面表示輸入引數名稱、型別和個數,右邊表示函式的實現和返回值型別和引數個數

作為值的函式


定義函式

scala> val func = (x:Int) => x * x

func: Int => Int = <function1>


scala> val func:Int => Int = x => x * x

func: Int => Int = <function1>


scala> func(3)

res0: Int = 9


函式呼叫

scala> val arr = Array(1,2,3,4)

arr: Array[Int] = Array(1, 2, 3, 4)


scala> val res = arr.map(x => func(x))

res: Array[Int] = Array(1, 4, 9, 16)


scala> val res = arr.map(func(_))

res: Array[Int] = Array(1, 4, 9, 16)


scala> val res = arr.map(func)

res: Array[Int] = Array(1, 4, 9, 16)


將方法轉化為函式

scala> def m1(x:Int):Int = x * x

m1: (x: Int)Int


scala> def m1(x:Int) = x * x

m1: (x: Int)Int


scala> def m2(x:Int) {x * x}

m2: (x: Int)Unit


scala> val f1 = m1 _

f1: Int => Int = <function1>


scala> val res = arr.map(x => m1(x))

res: Array[Int] = Array(1, 4, 9, 16)


scala> val res = arr.map(m1(_))

res: Array[Int] = Array(1, 4, 9, 16)


scala> val res = arr.map(m1)

res: Array[Int] = Array(1, 4, 9, 16)


匿名函式

在Scala中,你不需要給每一個函式命名,沒有將函式賦給變數的函式叫做匿名函式

scala> arr.map((x:Int) => x * x)

res3: Array[Int] = Array(1, 4, 9, 16)


scala> arr.map(x => x * x)

res4: Array[Int] = Array(1, 4, 9, 16)


scala> arr.map(m1)

res1: Array[Int] = Array(1, 4, 9, 16)


scala> arr.map(_ * 2)

res2: Array[Int] = Array(2, 4, 6, 8)


閉包

閉包就是能夠讀取其他函式內部變數的函式

可以理解成,定義在一個函式內部的函式

本質上,閉包是將函式內部和函式外部連結起來的橋樑

object Bibao {


  def sum(f:Int => Int):(Int,Int) => Int = {

    def sumf(a:Int,b:Int):Int = {

      if (a > b) 0 else f(a)+sumf(a + 1,b)

    }

    sumf  //隱式轉換成函式

  }

  def main(args: Array[String]): Unit = {

    def sumInts = sum(x => x)

    println(sumInts(1,2))

  }

}


柯里化

柯里化指的是將原來接收兩個引數列表的方法或函式變成新的一個引數列表的方法或函式的過程


宣告和轉化

scala> def curry(x:Int)(y:Int) = x * y  //宣告

curry: (x: Int)(y: Int)Int


scala> curry(3)(4)

res8: Int = 12


scala> val curry1 = curry(3) _  //轉換成方法 : 加"_"

curry1: Int => Int = <function1>


scala> curry1(5)

res9: Int = 15


scala> def curry2(x:Int) = (y:Int) => x * y  //宣告

curry2: (x: Int)Int => Int


scala> val func = curry2(2)  //直接轉化

func: Int => Int = <function1>


scala> func(4)

res16: Int = 8


scala> def curry3() = (x:Int) => x * x

curry3: ()Int => Int


scala> val func = curry3()    //轉化空參

func: Int => Int = <function1>


scala> func(3)

res17: Int = 9


柯里化需要與隱式轉換相結合

implicit  隱式的 -> 隱式值在當前會話中同型別只能定義一次,不同型別可定義多個

scala> def m1(x:Int)(implicit y:Int=5) = x * y

m1: (x: Int)(implicit y: Int)Int


scala> m1(3)

res10: Int = 15


scala> m1(3)(6)    //隱式值可以改變

res11: Int = 18


scala> implicit val x = 100  //定義成全域性的隱式值,可以覆蓋

x: Int = 100


scala> m1(3)(6)

res12: Int = 18


scala> m1(3)

res13: Int = 300


scala> implicit val y = "abc"

y: String = abc


案例: 把陣列中元祖的value相加

scala> val arr = Array(("xixi",1),("haha",2),("heihei",3))

arr: Array[(String, Int)] = Array((xixi,1), (haha,2), (heihei,3))


scala>  arr.foldLeft(0)(_ + _._2)  //(初始值)(上次計算結果+迴圈出的結果)

res15: Int = 6


Curry的Demo

object Context{   //一般情況會新建類,再在此地呼叫

  implicit val a = "yaoyao"

  implicit val b = 100

}

object Curry {


  //與變數沒有關係,系統自己匹配相同型別的值

  implicit val a = "yaoyao"

  implicit val b = 100


  def m1(str:String)(implicit name:String="xiaodan"){

    println(str + name)

  }


  def main(args: Array[String]): Unit = {

    import Context.a

    m1("Hello ")

  }

}


隱式轉換

作用: 隱式的對類的方法進行增強,豐富現有類庫的功能

隱式轉換:

繼承 -> 透過方法的重寫來對父類的方法增強

代理模式 -> 遠端代理,多用於網站,代理一個例項,可以對例項方法增強,在呼叫方法之前

        代理,方法之後環繞

    裝飾模式 -> 裝飾模式也叫包裝模式,用java讀取檔案時要用到IO流,也是對例項方法增強                          

    new BufferInputStream(new FileInputStream).read()

就是用到了裝飾模式和門面模式 ->

裝飾模式是顯示的包裝,隱式轉換就是隱式的做了包裝

門面模式起到了隱式包裝的作用


隱式轉換函式 : 是指以implicit關鍵字宣告的帶有單個引數的函式

案例: 用隱式轉換,實現從給定的URI直接能呼叫read方法讀取檔案內容

object MyPredef {


  //implicit def fileToRichFile(file:String) = new RichFile(file)


  implicit val fileToRichFile = (file:String) =>new RichFile(file)

}


object RichFile {

  def main(args: Array[String]): Unit = {

    val file = "e://wordcount.txt"


//    //顯示的實現了對file的方法增強

//    val richFile = new RichFile(file)

//    val content: String = richFile.read()

//    println(content)


    //隱式轉換

    import MyPredef.fileToRichFile

    val content = file.read()

    println(content)


  }

}


class RichFile(val file:String){

  //建立read方法

  def read():String = {

    Source.fromFile(file).mkString

  }

}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2654464/,如需轉載,請註明出處,否則將追究法律責任。

相關文章