我曾经尝试写过一次,但是由于规则有些分散,最终我还是放弃了。基本上,您必须掌握它。
也许最好集中在大括号和括号可以互换使用的地方:将参数传递给方法调用时。你可以用大括号如果更换括号,当且仅当该方法需要一个参数。例如:
List(1, 2, 3).reduceLeft{_ + _} // valid, single Function2[Int,Int] parameter
List{1, 2, 3}.reduceLeft(_ + _) // invalid, A* vararg parameter
但是,您需要了解更多信息才能更好地掌握这些规则。
使用parens增加了编译检查
Spray的作者建议使用圆括号,因为它们可以提高编译检查的效率。这对于Spray等DSL来说尤其重要。通过使用parens,您是在告诉编译器应该只给它一行。因此,如果您不小心给它两个或更多,它会抱怨。现在,花括号不是这种情况–例如,如果您忘记了某个位置的运算符,则您的代码将被编译,并且您会得到意想不到的结果,并且可能会发现很难发现的错误。下面是人为的(因为表达式是纯净的,至少会给出警告),但指出了这一点:
method {
1 +
2
3
}
method(
1 +
2
3
)
第一次编译,第二次给出error: ')' expected but integer literal found
。作者想写1 + 2 + 3
。
有人可能会说,对于带有默认参数的多参数方法来说,这是相似的。使用parens时,会意外地忘记逗号分隔参数的可能性。
细度
关于冗长性的一个经常被忽略的重要提示。使用大括号不可避免地会导致冗长的代码,因为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)
。这可能会引起混乱。
函数/部分函数文字,带有 case
Scala具有函数和部分函数文字的语法。看起来像这样:
{
case pattern if guard => statements
case pattern => statements
}
可以使用case
语句的其他唯一地方是match
and 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 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 )
因此,如果您需要声明,多个语句import
或类似内容,则需要花括号。并且因为表达式是语句,所以括号可能会出现在花括号内。但是有趣的是,代码块也是表达式,因此您可以在表达式中的任何位置使用它们:
( { 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 }
这不是方法调用,因此您不能以任何其他方式编写它。好吧,您可以将花括号放在的括号内condition
,也可以使用括号内的代码块的花括号:
while ({x < 10}) { (x += 1) }
因此,我希望这会有所帮助。