ZetCode

Scala 控制流

最后修改于 2023 年 1 月 10 日

在本文中,我们将展示如何在 Scala 中控制程序流。

当 Scala 程序运行时,代码会从上到下执行。程序流可以通过各种关键字进行更改,包括 if/elseforwhilematch

控制流结构可用于有条件地或多次执行代码。

Scala if 条件

if/then 关键字用于创建简单的条件测试。它可以与 else ifelse 关键字结合使用。

main.scala
import scala.util.Random

@main def main() =

    val r = Random.between(-10, 10)

    if r > 0 then
        println(s"positive value ($r)")
    else if r == 0 then
        println("zero value")
    else
        println(s"negative value ($r)")

我们随机选择一个值。根据结果值,我们打印一条消息。有三种可能的执行分支。

if r > 0 then
    println(s"positive value ($r)")

如果 if 关键字后的表达式为 true,则执行下一条语句。其他分支不执行。


可以选择使用 end if 关键字来终止 if 条件。

main.scala
@main def main() =

    val r = Random.between(-10, 10)

    if r > 0 then
        println(s"positive value ($r)")
    else if r == 0 then
        println("zero value")
    else
        println(s"negative value ($r)")
    end if

在程序中,我们使用 end if 结束 if 条件。


if/then 条件是表达式;它们可以返回值。

main.scala
import scala.util.Random

@main def main() =

    val r = Random.between(-10, 10)

    val res = if r > 0 then
        s"positive value ($r)"
    else if r == 0 then
        "zero value"
    else
        s"negative value ($r)"

    println(res)

在此示例中,if/then 表达式返回一个结果,该结果稍后会被打印。

Scala while 循环

while/do 关键字用于创建循环。它一直运行直到满足给定条件。

main.scala
@main def main() =

    val vals = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    val n = vals.length

    var i = 0
    var msum = 0

    while i < n do
        msum = msum + vals(i)
        i = i + 1

    println(msum)

我们有一个整数列表。我们使用 while 循环计算整数的总和。

val vals = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

val n = vals.length

我们获取列表的长度。

var i = 0
var msum = 0

i 变量是计数器,msum 是计算总和的变量。

while i < n do
    msum = msum + vals(i)
    i = i + 1

while 循环运行直到计数器小于列表的长度。在块内,我们将当前值添加到 msum 并增加计数器。

$ scala main.scala
55

Scala for 循环

使用 for/do 关键字,我们迭代值的集合。

main.scala
@main def main() =

    val vals = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    var msum = 0

    for e <- vals do
        msum = msum + e

    println(msum)

该示例计算列表中整数的总和。与使用 while 循环相比,我们获得了更简洁的代码。

for e <- vals do
    msum = msum + e

在 for 循环中,我们逐个遍历列表的元素。

带 Map 的 Scala for 循环

For 循环也用于遍历 Map。

main.scala
@main def main() =

    val cts = Map("sk" -> "Slovakia", "ru" -> "Russia",
        "de" -> "Germany", "no" -> "Norway")

    for (k, v) <- cts do println(s"${k} ${v}")

我们有一个简单的 Map。我们遍历 Map 并打印其元素。

$ scala main.scala
sk Slovakia
ru Russia
de Germany
no Norway

带 Range 的 Scala for 循环

For 循环可以与值范围一起使用。

main.scala
@main def main() =

    for n <- 1 to 10 do
        println(n)

使用 to 关键字创建整数范围。

for n <- 1 to 10 do
    println(n)

我们使用 for 循环将数字 1 到 10 打印到控制台。

$ scala main.scala
1
2
3
4
5
6
7
8
9
10

多个生成器

For 循环可以有多个生成器。

main.scala
@main def main() =

    val vals1 = List('A', 'B', 'C', 'D', 'E')
    val vals2 = List(1, 2, 3, 4, 5)

    val res = for
        e1 <- vals1
        e2 <- vals2
    yield
        s"$e1$e2"

    println(res)

使用两个 for 生成器,我们将两个列表的元素组合起来。

$ scala main.scala
List(A1, A2, A3, A4, A5, B1, B2, B3, B4, B5, C1, C2, C3, C4, C5, ...

Scala for 表达式

For 表达式返回一个值。For 表达式使用 for/yield 关键字创建。For 表达式也称为 for 推导式。

For 表达式构建新的数据集合。

main.scala
@main def main() =

    val nums =
        for i <- -5 to 5
        yield i * 2

    println(nums)

该示例使用 for 表达式创建了一个整数向量。

$ scala main.scala
Vector(-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10)

在下面的示例中,我们使用 for 推导式创建了一个新列表。

main.scala
case class User(name: String, age: Int)

val users = List(
  User("John", 18),
  User("Brian", 31),
  User("Veronika", 23),
  User("Lucia", 48),
  User("Peter", 21))

val res =

  for user <- users if user.age >= 20 && user.age < 30
  yield user


@main def main() =

    println(res)
    res.foreach(println)

我们有一个用户列表。使用 for 表达式,我们创建一个新列表,其中只包含年龄在 20 到 30 岁之间的用户。

$ scala main.scala
List(User(Veronika,23), User(Peter,21))
User(Veronika,23)
User(Peter,21)

Scala for 守卫

守卫是 for 表达式中的 if 表达式,可以有条件地包含值。

main.scala
@main def main() =

    val words = List("sky", "war", "water", "rain",
        "some", "cup", "train", "wrinkle", "worry")

    val res = for
        word <- words
        if word.startsWith("w")
    yield
        word

    println(res)

我们有一个字符串列表。我们使用 for 表达式遍历列表。但是,由于 if 守卫,最终输出中只包含以 'w' 开头的单词。

$ scala main.scala
List(war, water, wrinkle, worry)

可以包含多个守卫。

main.scala
@main def main() =

    val words = List("sky", "war", "water", "rain",
        "some", "cup", "train", "wrinkle", "worry")

    val res = for
        word <- words
        if word.startsWith("w")
        if word.endsWith("r")
    yield
        word

    println(res)

使用两个守卫,我们只包含以“w”开头并以“r”结尾的单词。

$ scala main.scala
List(war, water)

Scala match 表达式

模式匹配是一种强大的控制流结构,它允许我们将一个值与一系列模式进行比较,然后根据匹配的模式执行代码。

在 match 表达式中,每个被执行的选项称为一个 arm。

main.scala
@main def main() =

    val grades = List("A", "B", "C", "D", "E", "F", "FX")

    for grade <- grades do
        grade match
            case "A" | "B" | "C" | "D" | "E" | "F" => println("passed")
            case "FX" => println("failed")

我们有一个成绩列表。我们遍历列表并为每个值打印“通过”或“失败”。此示例使用多选项 arm,节省了大量空间。它比使用多个 if/else 关键字要短得多。

$ scala main.scala
passed
passed
passed
passed
passed
passed
failed

在本文中,我们学习了 Scala 中的控制流结构。