scala - 花括号和括号之间在Scala中的形式差异是什么?何时使用?

标签 scala syntax parentheses braces

将参数传递给括号()和括号{}中的函数有什么形式上的区别?

我从Programming in Scala书中得到的感觉是Scala非常灵活,我应该使用我最喜欢的那种,但是我发现有些情况下可以编译,而有些情况下则不需要。

例如(仅作为示例;我不胜感激任何讨论一般情况的回复,而不仅限于此特定示例):

val tupleList = List[(String, String)]()
val filtered = tupleList.takeWhile( case (s1, s2) => s1 == s2 )

=>错误:简单表达式的非法启动
val filtered = tupleList.takeWhile{ case (s1, s2) => s1 == s2 }

=>很好。

最佳答案

我曾经尝试写过一次,但是由于规则有些分散,最终我还是放弃了。基本上,您必须掌握它。
也许最好集中在大括号和括号可以互换使用的地方:将参数传递给方法调用时。仅在该方法需要单个参数的情况下,才可以用花括号替换括号。例如:

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 style guide明确指出,右花括号必须位于其自己的行上:

…最后一个括号紧跟在最后一行
函数行。

像IntelliJ中一样,许多自动重新格式化程序将自动为您重新格式化。因此,请尽量使用圆形括号。
中缀符号
当使用像List(1,2,3) indexOf (2)这样的中缀表示法时,如果只有一个参数,则可以省略括号并将其写为List(1, 2, 3) indexOf 2。这不是点符号的情况。
还要注意,当您有一个作为多 token 表达式的单个参数(例如x + 2a => a % 2 == 0)时,必须使用括号来指示表达式的边界。
元组
因为有时可以省略括号,所以有时元组需要额外的括号,例如((1, 2))中,有时可以省略外部括号,例如(1, 2)中。这可能会引起混乱。
case的函数/部分函数文字
Scala具有函数和部分函数文字的语法。看起来像这样:
{
    case pattern if guard => statements
    case pattern => statements
}
可以使用case语句的其他唯一地方是matchcatch关键字:
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) }
因此,我希望这会有所帮助。

关于scala - 花括号和括号之间在Scala中的形式差异是什么?何时使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51162270/

相关文章:

scala - 拦截 STDOUT 并通过 akka 进行流传输

scala - 如何有条件地调用 sbt 中的任务?

c# - LINQ:为什么叫 "Comprehension Syntax"

php - Try-Catch 未捕获自定义异常类型

vim - 保持括号平衡(Vim 的 Paredit?)

python - 如何从输出python中删除括号

list - 列表的::: 和++ 之间有什么区别?

scala - 没有架构的行上的 java.lang.UnsupportedOperationExceptionfieldIndex 未定义 : Exception on row. getAs[String]

javascript - jQuery 错误 : missing ( before formal parameters

java - Eclipse 自动格式化括号