scala:把函數作爲值或參數進行傳遞、作爲返回值進行返回,以及什麼是閉包和柯里化

@

函數可以作爲值進行傳遞

  • 語法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的永遠不能省略圓括號。
  • 匿名函數如果只有一行,則大括號也可以省略
  • 如果參數只出現一次,則參數省略且後面參數可以用_代替
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章