1. 程式人生 > >Scala函數語言程式設計筆記

Scala函數語言程式設計筆記

Scala中函式可以不依賴於類、物件、介面單獨存在,函式可以作為函式的引數、返回值。

scala> def fun1(name:String){println(name)}  //定義函式
fun1: (name: String)Unit

scala> val fun1_v = fun1 _  //將函式賦值給fun1_v
fun1_v: String => Unit = <function1>

scala> val fun1_v = fun1 _
fun1_v: String => Unit = <function1>

scala>
fun1("spark") spark scala> fun1_v("spark") spark

匿名函式:為了使用簡潔,將函式直接賦值給變數,使用函式時通過呼叫變數實現,稱為匿名函式。

scala> val fun2 = (content:String) => println(content)   //定義匿名函式
fun2: String => Unit = <function1>

scala> fun2("Spark")
Spark

高階函式:即某個函式的引數或返回值也是函式。

scala> val hiScala = (content:String)
=>
println(content) //定義匿名函式 hiScala: String => Unit = <function1> scala> def bigData(func:(String) => Unit, content:String){func(content)} //定義高階函式 bigData: (func: String => Unit, content: String)Unit scala> bigData(hiScala, "Spark") Spark
scala> val array = Array(1,2
,3,4,5,6,7,8,9) array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) scala> array.map(item => item * 2) //map內參數為匿名函式 res5: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16, 18)
//返回值為函式舉例
scala> def func_Returned(content:String) = (message:String) => println(content + " " + message)
func_Returned: (content: String)String => Unit

scala> val returned = func_Returned("Spark")
returned: String => Unit = <function1>

scala> returned("Scala")
Spark Scala

如果在函式的函式體中,某個輸入引數的值只使用了一次,此時可以將引數名稱省略,用下劃線“_”表示。

scala> def spark(func:(String) => Unit, name:String){func(name)}
spark: (func: String => Unit, name: String)Unit

scala> spark((name:String) => println(name), "Scala")
Scala

scala> spark(name => println(name), "Scala") //型別推斷
Scala

scala> spark(println(_), "Scala")  //進一步簡化
Scala

scala> spark(println, "Scala")  //只有一個引數,直接省略
Scala

scala> val array = Array(1,2,3,4,5,6,7,8,9)
array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> array.map(_*2).filter(_ > 10).foreach(println)
12
14
16
18

閉包:函式的變數超出其有效作用域時,仍然可以對函式內部變數進行訪問。

scala> def scala(content:String) = (message:String) => println(content + " " + message)
scala: (content: String)String => Unit

scala> val funcResult = scala("Spark")  //執行完畢後content的內容仍然可以被訪問
funcResult: String => Unit = <function1>

scala> funcResult("Flink")  //此時變數content的值Spark超出了函式scala的作用域,但依舊可以成功訪問,即為閉包
Spark Flink

閉包內部實現原理:Scala內部自動生成了一個函式物件,把變數作為該物件的成員,而函式本身也是物件的成員,執行函式後,函式的返回結果也是該物件的成員,自然可以進行變數的呼叫。

函式柯里化:是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數而且返回結果的新函式的技術。柯里化本身也用到了閉包。

//未柯里化
scala> def sum(x:Int, y:Int) = x + y
sum: (x: Int, y: Int)Int

scala> sum(1, 2)
res14: Int = 3

//柯里化
scala> def sum_Currying(x:Int) = (y:Int) => x + y
sum_Currying: (x: Int)Int => Int

scala> sum_Currying(1)(2)
res19: Int = 3

//程式碼簡化
scala> def sum_Currying_better(x:Int)(y:Int) = x + y
sum_Currying_better: (x: Int)(y: Int)Int

scala> sum_Currying_better(1)(2)
res21: Int = 3

將兩個引數的函式變成了兩個函式的連續呼叫。

scala> (1 to 100).reduceLeft(_+_)  //1+2=3,3+3=6...
res22: Int = 5050

集合的高階函式操作:

scala> val list = List("scala", "spark")
list: List[String] = List(scala, spark)

scala> val cal = list.map("The content is: " + _)
cal: List[String] = List(The content is: scala, The content is: spark)

scala> cal.flatMap(_.split(" "))
res25: List[String] = List(The, content, is:, scala, The, content, is:, spark)

scala> list.zip(List(1,2))
res26: List[(String, Int)] = List((scala,1), (spark,2))