Scala入门03——Scala函数

在上一章当中,我们定义函数的方法是适用于无参的函数的,接下来,我们一起来学习函数声明的完整方法

基本函数声明

上一章的声明方法:

1
2
3
4
5
6
7
8
scala> val x = 1
x: Int = 1

scala> val y = 2
y: Int = 2

scala> def sum = x + y
sum: Int

完整的函数声明方法:

1
2
3
4
scala> def sum(x : Int, y : Int): Int = {
| x + y
| }
sum: (x: Int, y: Int)Int

补充:右括号右边的: Int代表本函数的返回值类型,=代表这是一个有返回值的函数,如果: Int=省略,等于: Unit=,即返回()

我们可以让Scala自动推断返回值类型,即可以这样书写:

1
2
3
4
scala> def sum(x : Int, y : Int) = {
| x + y
| }
sum: (x: Int, y: Int)Int

补充:不过要记得,=一般不能省略,否则等于返回值为()

if的使用

我们也可以尝试实现一下if语句,这是最基本的程序流程控制语句

1
2
3
4
5
6
7
8
scala> def max(x : Int, y : Int): Int = {
| if (x > y){
| return x
| } else {
| return y
| }
| }
max: (x: Int, y: Int)Int

以上程序无比的完整,但是他太繁琐了,我们可以尝试这样去书写它:

1
2
scala> def max(x : Int, y : Int) = if (x > y) x else y
max: (x: Int, y: Int)Int

我们可以把如上函数看做Java语言当中的三元表达式或者称为三目运算

补充:必须要告诉大家的是,Scala会返回程序执行中函数最后一行的值,而无需使用return

函数的使用

(1)函数的默认值

函数的参数可以拥有自己的默认值,如果调用者没有传递相应的参数,则使用默认值

1
2
3
4
5
6
7
8
def sayMyName(name : String = "Marry") = {
println(name)
}

def main(args: Array[String]): Unit = {
sayMyName()
sayMyName("Jack")
}

补充:Scala建议的缩进是两个空格

(2)可变长函数

当不确定函数需要接受几个参数的时候,使用可变长函数

1
2
3
4
5
6
7
8
9
def printElement(x : Int*) = {
for (element <- x){
println(element)
}
}

def main(args: Array[String]): Unit = {
printElement(1, 2, 3)
}

(3)调用函数的函数

我们先有这样一个函数,用于计算两个数的和

1
2
3
4
5
def add(x : Int, y : Int) = x + y

def main(args: Array[String]): Unit = {
println(add(2, 3))
}

以上函数的执行结果显然是:5

如果我们能够确定其中一个函数的参数,那么我们的函数2可以这样书写

1
2
3
4
5
6
7
def add(x : Int, y : Int) = x + y

def add2 = add(_ : Int, 2)

def main(args: Array[String]): Unit = {
println(add2(8))
}

以上函数,_代表通配符,意为任意一个Int类型的参数,2代表固定的参数

add2()的书写方法为该方式的简写:

1
def add2(x : Int) = add(x, 2)

(4)函数递归

例:计算5的阶乘

1
2
3
4
5
def fac (x : Int): Int = if (x == 1) 1 else fac(x - 1) * x

def main(args: Array[String]): Unit = {
println(fac(5))
}

(5)柯里化函数

柯里化函数是一种特殊的书写方式:

1
2
3
4
5
def mulitply(x : Int)(y : Int) = x * y

def main(args: Array[String]): Unit = {
println(mulitply(2)(3))
}

函数互相调用(柯里化函数中通配符的使用):

1
2
3
4
5
6
def mulitply(x : Int)(y : Int) = x * y
def mulitply2 = mulitply(3)_

def main(args: Array[String]): Unit = {
println(mulitply2(3))
}

(6)匿名函数

在Scala中声明一个匿名函数,方法如下

1
2
3
4
5
val t = () => 333

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

将匿名函数作为参数

1
2
3
4
5
6
7
8
9
val t = () => 333

def testFunc(c : () => Int) = {
println(c())
}

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

补充:上述函数,若println()函数内传递的是c,而不是c(),将打印其内存地址;c()为调用该函数

() => Int为匿名函数的类型:即无参、返回类型为Int

举例:

1
2
3
4
5
6
7
8
9
def testF1(callback: (Int, Int) => Int) = {
callback(123, 123)
}

val addFunc = (x: Int, y: Int) => {x + y}

def main(args: Array[String]): Unit = {
println(testF1(addFunc))
}

(7)嵌套函数

1
2
3
4
5
6
7
8
9
10
def funOut(x: Int, y:Int, z: Int) = {
def funInner(x: Int, y: Int) = {
x + y
}
funInner(funInner(x, y), z)
}

def main(args: Array[String]): Unit = {
println(funOut(1, 2, 3))
}

小测验:能否看懂

1
2
3
4
5
6
7
8
9
10
11
12
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 = {
val f = (x: Int) => x
val sumF = sum(f)
println(sumF(1, 2))
}

分析:

本题意为:

  • sum()函数,入参f,类型为匿名函数:入参Int;出参Int

  • sum()函数,出参为匿名函数:入参Int,Int;出参Int

  • sumF()函数为sum()函数的嵌套函数,入参a,b皆为Int;出参为Int

  • sumF()函数体:如果a > b,则返回0;否则返回f匿名函数(传入a)和递归调用sumF()函数(传入a + 1,b)的和

main方法测试:

给sum()函数传递一个符合要求的匿名函数即可得到一个sumF()函数

给sumF()函数传值

1 + sumF(2, 2)
|
|
1 + 2 + sumF(3, 2)
|
|
1 + 2 + 0