Scala 3 — Book

# 控制结构

Language

Scala 具有您在其他编程语言中可以找到的控制结构，并且还具有强大的 `for` 表达式和 `match` 表达式：

• `if`/`else`
• `for` 循环和表达式
• `match` 表达式
• `while` 循环
• `try`/`catch`

## `if`/`else`

Scala 的 `if`/`else` 控制结构看起来与其他语言相似：

``````if (x < 0) {
println("negative")
} else if (x == 0) {
println("zero")
} else {
println("positive")
}
``````
``````if x < 0 then
println("negative")
else if x == 0 then
println("zero")
else
println("positive")
``````

``````val x = if (a < b) { a } else { b }
``````
``````val x = if a < b then a else b
``````

## `for` 循环和表达式

`for` 关键字用于创建 `for` 循环。 这个例子展示了如何打印 `List` 中的每个元素：

``````val ints = List(1, 2, 3, 4, 5)

for (i <- ints) println(i)
``````

``````val ints = List(1, 2, 3, 4, 5)

for i <- ints do println(i)
``````

### 守卫

``````for (i <- ints if i > 2)
println(i)
``````
``````for
i <- ints
if i > 2
do
println(i)
``````

``````for {
i <- 1 to 3
j <- 'a' to 'c'
if i == 2
if j == 'b'
} {
println(s"i = \$i, j = \$j")   // prints: "i = 2, j = b"
}
``````
``````for
i <- 1 to 3
j <- 'a' to 'c'
if i == 2
if j == 'b'
do
println(s"i = \$i, j = \$j")   // prints: "i = 2, j = b"
``````

### `for` 表达式

`for` 关键字更强大：当您使用 `yield` 关键字代替 `do` 时，您会创建 `for` _表达式_用于计算和产生结果。

``````scala> val doubles = for (i <- ints) yield i * 2
val doubles: List[Int] = List(2, 4, 6, 8, 10)
``````
``````scala> val doubles = for i <- ints yield i * 2
val doubles: List[Int] = List(2, 4, 6, 8, 10)
``````

Scala 的控制结构语法很灵活，`for` 表达式可以用其他几种方式编写，具体取决于您的偏好：

``````val doubles = for (i <- ints) yield i * 2
val doubles = for (i <- ints) yield (i * 2)
val doubles = for { i <- ints } yield (i * 2)
``````
``````val doubles = for i <- ints yield i * 2     // 如上所示的风格
val doubles = for (i <- ints) yield i * 2
val doubles = for (i <- ints) yield (i * 2)
val doubles = for { i <- ints } yield (i * 2)
``````

``````val names = List("chris", "ed", "maurice")
val capNames = for (name <- names) yield name.capitalize
``````
``````val names = List("chris", "ed", "maurice")
val capNames = for name <- names yield name.capitalize
``````

``````val fruits = List("apple", "banana", "lime", "orange")

val fruitLengths =
for (f <- fruits if f.length > 4) yield f.length

// fruitLengths: List[Int] = List(5, 6, 6)
``````
``````val fruits = List("apple", "banana", "lime", "orange")

val fruitLengths = for
f <- fruits
if f.length > 4
yield
// 在这里你可以
// 使用多行代码
f.length

//fruitLengths: List[Int] = List(5, 6, 6)
``````

`for` 循环和表达式更多细节在本书的 控制结构部分 中，和 参考文档 中。

## `match` 表达式

Scala 有一个 `match` 表达式，它最基本的用途类似于 Java `switch` 语句：

``````val i = 1

// later in the code ...
i match {
case 1 => println("one")
case 2 => println("two")
case _ => println("other")
}
``````
``````val i = 1

// later in the code ...
i match
case 1 => println("one")
case 2 => println("two")
case _ => println("other")
``````

``````val result = i match {
case 1 => "one"
case 2 => "two"
case _ => "other"
}
``````
``````val result = i match
case 1 => "one"
case 2 => "two"
case _ => "other"
``````

`match` 不仅限于使用整数值，它可以用于任何数据类型：

``````val p = Person("Fred")

// later in the code
p match {
case Person(name) if name == "Fred" =>
println(s"\$name says, Yubba dubba doo")

case Person(name) if name == "Bam Bam" =>
println(s"\$name says, Bam bam!")

case _ => println("Watch the Flintstones!")
}
``````
``````val p = Person("Fred")

// later in the code
p match
case Person(name) if name == "Fred" =>
println(s"\$name says, Yubba dubba doo")

case Person(name) if name == "Bam Bam" =>
println(s"\$name says, Bam bam!")

case _ => println("Watch the Flintstones!")
``````

``````// getClassAsString is a method that takes a single argument of any type.
def getClassAsString(x: Any): String = x match {
case s: String => s"'\$s' is a String"
case i: Int => "Int"
case d: Double => "Double"
case l: List[_] => "List"
case _ => "Unknown"
}

// examples
getClassAsString(1)               // Int
getClassAsString("hello")         // 'hello' is a String
getClassAsString(List(1, 2, 3))   // List
``````

``````// getClassAsString 是一个接受任何类型的单个参数的方法。
def getClassAsString(x: Matchable): String = x match
case s: String => s"'\$s' is a String"
case i: Int => "Int"
case d: Double => "Double"
case l: List[_] => "List"
case _ => "Unknown"

// examples
getClassAsString(1)               // Int
getClassAsString("hello")         // 'hello' is a String
getClassAsString(List(1, 2, 3))   // List
``````

`getClassAsString` 方法将 Matchable 类型的值作为参数，它可以是 任何支持模式匹配的类型（某些类型不支持模式匹配，因为这可能打破封装）。

Scala 中的模式匹配还有 更多 内容。 模式可以嵌套，模式的结果可以绑定，模式匹配甚至可以是用户自定义的。 有关详细信息，请参阅 控制结构章节 中的模式匹配示例。

## `try`/`catch`/`finally`

Scala 的 `try`/`catch`/`finally` 控制结构让你捕获异常。 它类似于 Java，但其语法与 `match` 表达式一致：

``````try {
writeTextToFile(text)
} catch {
case ioe: IOException => println("Got an IOException.")
case nfe: NumberFormatException => println("Got a NumberFormatException.")
} finally {
println("Clean up your resources here.")
}
``````
``````try
writeTextToFile(text)
catch
case ioe: IOException => println("Got an IOException.")
case nfe: NumberFormatException => println("Got a NumberFormatException.")
finally
println("Clean up your resources here.")
``````

## `while` 循环

Scala 还有一个 `while` 循环结构。 它的单行语法如下所示：

``````while (x >= 0) { x = f(x) }
``````
``````while x >= 0 do x = f(x)
``````

`while` 循环多行语法如下所示：

``````var x = 1

while (x < 3) {
println(x)
x += 1
}
``````
``````var x = 1

while
x < 3
do
println(x)
x += 1
``````