六、函數
函數三要素:函數名、參數、函數體
聲明函數語法
def functionName ([參數列表]) : [return type] = { 函數體}
示例
// 無返回值
def sayHi(str: String): Unit = {
println("Hello:" + str)
}
// 可省略返回值類型,支持自動推導
def sum(x: Int, y: Int) = x + y
def multi(x: Double, y: Double): Double = x * y
總結:
- 有返回值的函數,
: 返回值類型 = {函數代碼塊}
或者= {函數代碼塊}
- 無返回值的函數,
:Unit = {函數代碼塊}
或者{}
變長參數
package function
object Function02 {
// 主函數聲明
def main(args: Array[String]) {
println(sum(1, 2, 3, 4, 5))
println(sum(1))
println(sum())
}
// 變長參數列表 n1 n2... nn
// 語法:變量名:類型*
def sum(nn: Int*): Int = {
var sum = 0
for (n <- nn) {
sum += n
}
sum
}
// 注意: 如果有多個參數,可變長參數需要寫在所有參數之後
def sum2(default: Int,nn: Int*): Int = {
var sum = 0
for (n <- nn) {
sum += n
}
sum
}
}
參數默認值
package function
object Function03 {
def main(args: Array[String]): Unit = {
println(m1("Welcome"))
// 無給定值,使用默認值
println(m2())
// 給定值,使用給定值
println(m2("welcome", 20, 100.0))
// 部分參數使用給定值,另一部分參數使用默認值
println(m2("welcome"))
// 給特定的參數賦予給定值,其餘使用默認值
println(m2(arg2 = 100))
}
// 默認值函數
def m1(arg1: String = "Hello"): String = {
arg1
}
// 默認值函數
// 注意:函數不支持重載,只有方法支持重載
def m2(arg1: String = "Hello", arg2: Int = 10, arg3: Double = 10.0): String = {
arg1 + "\t" + arg2 + "\t" + arg3
}
}
帶名參數
m1(arg2 = 100, arg1 = "new value")
def m1(arg1: String = "default value1", arg2: Int = 10): Unit ={
println (arg1 + "\t" + arg2)
}
//new value <---> 100
Lazy值
懶加載,當val被聲明爲lazy時,它的初始化將被推遲,直到我們首次對它取值。
import scala.io.Source._
/**
* lazy值 使用時初始化 節省資源
*/
object function03 {
def main(args: Array[String]): Unit = {
val file1 = fromFile("").mkString
println(file1)
// lazy val file2 = fromFile("").mkString
// println(file2)
}
}
遞歸函數
遞歸求1到n之和
def sum(n: Int): Int = {
var total = 0
if (n >= 1) {
total = n + sum(n - 1)
}
total
}
遞歸求1到n的階乘
def factorial(n: Int): Int = {
if (n > 1) {
n * factorial(n - 1)
} else {
1
}
}
匿名函數
Scala 中定義匿名函數的語法很簡單,箭頭左邊是參數列表,右邊是函數體。使用匿名函數後,我們的代碼變得更簡潔了。
package function
/**
* 遞歸使用
*/
object Function05 {
def main(args: Array[String]): Unit = {
// 匿名函數: 沒有函數名
val f1: Function2[Int, Int, Int] = (x: Int, y: Int) => x + y
println(f1)
val f2 = () => "Hello:"
println(f2)
val f3 = (x: Int, y: Int, z: Int) => x * y * z
println(f3)
List("a", "b").foreach(n => println(n))
/*
<function2>
<function0>
<function3>
a
b
*/
println(f1(1,2))
println(f2())
println(f2) // 打印對象,注意:沒有參數的匿名函數需要加()調用
println(f3(2,2,2))
}
}
注意:
- 匿名函數返回的是一個函數對象(Function,scala提供了23個函數對象,分別對應0到22個參數)
柯里化(Currying)
柯里化(Currying)指的是將原來接受兩個參數的函數變成新的接收一個參數的函數的過程。新的函數返回一個以原有第二個參數爲參數的函數。
package function
/**
* 柯里化函數(curring)
* 將多個參數的函數 轉換爲接收一個參數函數的過程,就稱爲柯里化,並返回以第二個參數爲參數的函數
*/
object Function06 {
def main(args: Array[String]): Unit = {
println(sum2(1)(6))
println(sum3(1)(6))
println(sum4(1)(6)(2))
println(sum4 _)
}
// 普通函數
def sum1(x: Int, y: Int): Int = {
x + y
}
// 柯里化函數
def sum2(x: Int) = (y: Int) => x + y
// 柯里化函數 簡化寫法
def sum3(x: Int)(y: Int) = x + y
def sum4(x: Int)(y: Int)(z: Int) = x + y + z
}