scala基础3 —— 表达式和控制结构

来源:互联网 发布:.net域名代表什么 编辑:程序博客网 时间:2024/06/08 09:59

在java或者c++等这些语言中,表达式和语句(if等)是完全分开的,表达式最终是一个值,二语句执行一个动作,但是,scala和其他编程语言的一个根本差别就是,在scala的世界里,所有的东西都可以认为有一个值,常规的表达式,其他结构化语句(if语句,块语句等),都有一个值。

块表达式

scala中块语句也是一个表达式,有值,其值就是块中最后一个表达式的值,比如

var v = {      var x1 = 4      var x2 = 5      max(x1, x2)    }

v的值就是max调用返回的值。

赋值语句

赋值语句单独拿出来说,是因为,赋值语句是没有值的,或者说值为Unit,因此将赋值语句作为块表达式结尾或者在函数中使用的时候要格外小心。

var x = y = 5 // 这个和期望结果不同,x不为5

条件表达式

scala的if/else语句和java/c++一样,不同的是scala的条件语句有值,并且可以赋值给变量,比如:

if (x > 0) 1 else -1val v = if (x > 0) 1 else -1

scala中没有?:表达式,而是把这个和if/else语句结合在一起了。

scala中每个语句都有一个值,因此,如果if/else返回的类型不同,或者只有if怎么办?不用担心,scala还有内置的类型Any和Unit。
Any是任何类型的超类,Unit相当于java中的void,但是有一点区别就是void没有值,Unit表示“无值”的值,比如:

var v : Any = if (x > 0) "str" else 1

另,多个分支时候,使用的是if/else if/else格式,同java一样。

循环语句

scala的while、do循环语句和java一样,比如:

// while语句var x = 100    while (x > 0) {      x -= 1    }// do-while语句do {      x -= 1    } while (x > 0)

for循环语句和java不太一样,scala的for循环语句语法结构如下:

for (v <- 表达式)

即以此遍历表达式中的每个值,并赋值给v,比如

def forTest(): Unit = {    for (x <- 0 to 10) { // 包括10      print(x)    }    for (x <- 0 until 10) { // 不包括10      print(x)    }    var r = Range(0, 10) // 不包括10    for (x <- r) {      print(x)    }    for (ch <- "string") { // 遍历每个字符      print(ch)    }  }

scala中没有break和continue来跳出循环和继续,可以考虑Boolean值控制和从函数中return。
其实,for循环的功能还可以更丰富,比如多个条件:

for (x <- 1 to 10; y <- 1 to 10) {   println(x + y)}

带守卫的for循环,守卫就是if开头的Boolean表达式,比如:

for (x <- 1 to 10 if x % 2 != 0) { // 注意,if前面没有分号   print(x)}

for推导式,如果for循环体以yield开头,该循环会构造出一个集合,每次循环生成集合中的一个值,比如:

val forVal = for (x <- 1 to 10) yield x % 3println(forVal) // 输出为Vector(1, 2, 0, 1, 2, 0, 1, 2, 0, 1)

分支语句

scala没有switch分支语句,但是有更强大的模式匹配机制,除了switch场景,还能应用于很多场景。预java的switch对应的是match,语句switch中default等效的是case _,在scala中下划线_代表任意匹配,在多种场景可以使用。
scala中match的特点是:
1. 每个匹配完成不需要break,会自动跳出,不会有意外进入下一个分支的问题。
2. 如果没有匹配项,会跑出异常MatchError,可以通过case _来避免
3. match语句也是表达式,可以直接赋值给变量
比如:

var flag = 0var ch = "c"ch match {  case "a" => flag = 0  case "b" => flag = 1  case "c" => flag = 2  case _ => flag = -1}// 或者flag = ch match {  case "a" => 0  case "b" => 1  case "c" => 2  case _ => -1}  

另,模式中也可以包含守卫(if + Boolean表达式),来扩展我们的匹配功能,比如:

var ch = "c"ch match {  case "a" => 0  case "b" => 1  case "c" => 2  case _ if Character.isDigit(ch) => Character.digit(ch, 10) // 添加守卫,判断条件  case _ => -1}

另,模式中case后面也可以使用变量,表示将匹配项赋值给该变量,可以看做是_的特例情况。

ch match {  case "a" => 0  case "b" => 1  case "c" => 2  case v => Character.digit(v) // 将匹配项赋值给变量v  case _ => -1}

另,scala也可以对类型进行模式匹配,并且变量是必须给出的,比如:

obj match {  case x : Int => x // Int类型  case s : String => Integer.valueOf(s) // String类型  case _ : BigInt => Int.MaxValue // BigInt类型  case _ => 0}

其他,还有更多的匹配数组等集合情况先不在这里讲。

0 0