样式指南

控制结构

语言

所有控制结构都应在定义关键字后用空格编写

// 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 推导优于对 mapflatMapfilter 的链式调用,因为这可能难以阅读(这是增强 for 推导的目的之一)。

平凡条件

在某些情况下,为在较大表达式中嵌套使用创建简短的 if/else 表达式很有用。在 Java 中,这种情况下通常由三元运算符 (?/:) 处理,Scala 缺少这种语法设备。在这些情况下(以及实际上任何时候你都有一个非常简短的 if/else 表达式),允许将“then”和“else”分支放在与 ifelse 关键字相同的行上

val res = if (foo) bar else baz

这里的关键是可读性不受将两个分支与 if/else 内联移动的影响。请注意,此样式绝不应与命令式 if 表达式一起使用,也不应使用大括号。

此页面的贡献者