所有控制结构都应在定义关键字后用空格编写
// right!
if (foo) bar else baz
for (i <- 0 to 10) { ... }
while (true) { println("Hello, World!") }
// wrong!
if(foo) bar else baz
for(i <- 0 to 10) { ... }
while(true) { println("Hello, World!") }
大括号
在控制结构表示纯函数操作且控制结构的所有分支(与 if
/else
相关)都是单行表达式的情况下,应省略大括号。请记住以下准则
if
- 如果有else
子句,则省略大括号。否则,即使内容只有一行,也要用大括号将内容括起来。while
- 永远不要省略大括号(while
不能以纯函数的方式使用)。for
- 如果有yield
子句,则省略大括号。否则,即使内容只有一行,也要用大括号将内容括起来。case
- 在 case 子句中始终省略大括号。
val news = if (foo)
goodNews()
else
badNews()
if (foo) {
println("foo was true")
}
news match {
case "good" => println("Good news!")
case "bad" => println("Bad news!")
}
推导
Scala 能够用多个生成器(通常是多个 <-
符号)表示 for
推导。在这种情况下,可以使用两种替代语法
// wrong!
for (x <- board.rows; y <- board.files)
yield (x, y)
// right!
for {
x <- board.rows
y <- board.files
} yield (x, y)
虽然后一种风格更冗长,但通常被认为更容易阅读且更“可扩展”(这意味着随着推导的复杂性增加,它不会变得晦涩难懂)。对于所有有多个生成器的 for
推导,你都应该首选此形式。仅具有单个生成器的推导(例如 for (i <- 0 to 10) yield i
)应使用第一种形式(括号而不是大括号)。
此规则的例外情况是缺少 yield
子句的 for
-推导。在这种情况下,该构造实际上是一个循环,而不是一个函数推导,并且通常将生成器串联在括号中比使用语法混乱的 } {
构造更具可读性
// wrong!
for {
x <- board.rows
y <- board.files
} {
printf("(%d, %d)", x, y)
}
// right!
for (x <- board.rows; y <- board.files) {
printf("(%d, %d)", x, y)
}
最后,for
推导优于对 map
、flatMap
和 filter
的链式调用,因为这可能难以阅读(这是增强 for
推导的目的之一)。
平凡条件
在某些情况下,为在较大表达式中嵌套使用创建简短的 if
/else
表达式很有用。在 Java 中,这种情况下通常由三元运算符 (?
/:
) 处理,Scala 缺少这种语法设备。在这些情况下(以及实际上任何时候你都有一个非常简短的 if
/else
表达式),允许将“then”和“else”分支放在与 if
和 else
关键字相同的行上
val res = if (foo) bar else baz
这里的关键是可读性不受将两个分支与 if
/else
内联移动的影响。请注意,此样式绝不应与命令式 if
表达式一起使用,也不应使用大括号。