我曾经试着写过这方面的文章,但最后还是放弃了,因为规则有点分散。基本上,你得掌握窍门。
也许最好集中在大括号和圆括号可以互换使用的地方:向方法调用传递参数时。当且仅当方法需要单个参数时,可以将花括号替换为圆括号。例如:
List(1, 2, 3).reduceLeft{_ + _} // valid, single Function2[Int,Int] parameter
List{1, 2, 3}.reduceLeft(_ + _) // invalid, A* vararg parameter
然而,要更好地掌握这些规则,你还需要了解更多。
增加了使用paren的编译检查
The authors of Spray recommend round parens because they give increased compile checking. This is especially important for DSLs like Spray. By using parens you are telling the compiler that it should only be given a single line; therefore if you accidentally give it two or more, it will complain. Now this isn’t the case with curly braces – if for example you forget an operator somewhere, then your code will compile, and you get unexpected results and potentially a very hard bug to find. Below is contrived (since the expressions are pure and will at least give a warning), but makes the point:
method {
1 +
2
3
}
method(
1 +
2
3
)
第一个编译,第二个给出错误:')'期望但发现整数字面量。作者想写1 + 2 + 3。
有人可能会说,这与带默认参数的多参数方法类似;在使用paren时,不可能不小心忘记用逗号分隔参数。
冗长
关于冗长,一个经常被忽视的重要注意事项。使用花括号不可避免地会导致冗长的代码,因为Scala风格指南明确指出,右花括号必须在它们自己的行上:
闭大括号在最后一个大括号后面的另一行上
函数的直线。
许多自动重新格式化程序(如IntelliJ)将自动为您执行这种重新格式化。所以尽量坚持使用圆括号。
中缀表示法
当使用中缀表示法时,如List(1,2,3) indexOf(2),如果只有一个参数,可以省略括号,并将其写成List(1,2,3) indexOf 2。这不是点符号的情况。
还要注意,当您有一个多令牌表达式的单个参数时,例如x + 2或a => a % 2 == 0,您必须使用圆括号来指示表达式的边界。
元组
因为有时可以省略圆括号,有时元组需要额外的圆括号,如in((1,2)),有时可以省略外圆括号,如in(1,2)。这可能会导致混淆。
带大小写的函数字面量
Scala有函数和部分函数字面量的语法。它是这样的:
{
case pattern if guard => statements
case pattern => statements
}
你可以使用case语句的唯一其他地方是match和catch关键字:
object match {
case pattern if guard => statements
case pattern => statements
}
try {
block
} catch {
case pattern if guard => statements
case pattern => statements
} finally {
block
}
您不能在任何其他上下文中使用case语句。如果你想用case,你需要花括号。如果您想知道函数和部分函数之间的区别是什么,答案是:上下文。如果Scala需要一个函数,你就会得到一个函数。如果它期望一个偏函数,你就得到一个偏函数。如果两者都是预期的,则给出关于歧义的错误。
表达式和块
括号可以用来生成子表达式。花括号可以用来组成代码块(这不是一个字面函数,所以要小心试图像使用它一样使用它)。代码块由多条语句组成,每个语句可以是import语句、声明或表达式。它是这样的:
{
import stuff._
statement ; // ; optional at the end of the line
statement ; statement // not optional here
var x = 0 // declaration
while (x < 10) { x += 1 } // stuff
(x % 5) + 1 // expression
}
( expression )
如果你需要声明,多条语句,一个导入或者类似的东西,你需要花括号。由于表达式是语句,括号可以出现在花括号内。但有趣的是,代码块也是表达式,所以你可以在表达式中的任何地方使用它们:
( { var x = 0; while (x < 10) { x += 1}; x } % 5) + 1
因此,由于表达式是语句,代码块是表达式,下面的所有内容都是有效的:
1 // literal
(1) // expression
{1} // block of code
({1}) // expression with a block of code
{(1)} // block of code with an expression
({(1)}) // you get the drift...
它们不能互换的地方
基本上,你不能用()替换{},反之亦然。例如:
while (x < 10) { x += 1 }
这不是一个方法调用,所以不能以其他方式编写它。好吧,你可以把花括号放在括号内的条件,以及使用括号在花括号内的代码块:
while ({x < 10}) { (x += 1) }