大括号和圆括号在Scala中的形式差异是什么,何时使用它们?

大括号和圆括号在Scala中的形式差异是什么,何时使用它们?,scala,syntax,parentheses,braces,Scala,Syntax,Parentheses,Braces,在括号()和大括号{}中向函数传递参数的形式上有什么区别 我从这本书中得到的感觉是Scala非常灵活,我应该使用我最喜欢的一个,但我发现有些案例可以编译,而其他的则不能 例如(只是作为一个示例;我希望任何讨论一般情况的回复,而不仅仅是这个特定示例): =>错误:简单表达式的开始非法 val filtered = tupleList.takeWhile{ case (s1, s2) => s1 == s2 } =>很好。因为您使用的是case,所以您定义的是分部函数,分部函数需要大括号。因

在括号
()
和大括号
{}
中向函数传递参数的形式上有什么区别

我从这本书中得到的感觉是Scala非常灵活,我应该使用我最喜欢的一个,但我发现有些案例可以编译,而其他的则不能

例如(只是作为一个示例;我希望任何讨论一般情况的回复,而不仅仅是这个特定示例):

=>错误:简单表达式的开始非法

val filtered = tupleList.takeWhile{ case (s1, s2) => s1 == s2 }

=>很好。

因为您使用的是
case
,所以您定义的是分部函数,分部函数需要大括号。

因为您使用的是
case
,您正在定义一个分部函数,分部函数需要大括号。

社区正在努力标准化大括号和圆括号的使用,请参见Scala样式指南(第21页):

高阶方法调用的推荐语法是始终使用大括号,并跳过点:

val filtered = tupleList takeWhile { case (s1, s2) => s1 == s2 }
对于“正常”metod调用,应使用点和括号

val result = myInstance.foo(5, "Hello")

社区正在努力使大括号和圆括号的使用标准化,请参见Scala样式指南(第21页):

高阶方法调用的推荐语法是始终使用大括号,并跳过点:

val filtered = tupleList takeWhile { case (s1, s2) => s1 == s2 }
对于“正常”metod调用,应使用点和括号

val result = myInstance.foo(5, "Hello")

这里有两种不同的规则和推论:首先,当参数是函数时,Scala推断大括号,例如在
list.map(*2)
中,大括号是推断的,它只是
list.map({u*2})
的一种较短形式。其次,Scala允许您跳过最后一个参数列表上的括号,如果该参数列表有一个参数并且它是一个函数,那么
list.foldLeft(0)({u+}
可以写成
list.foldLeft(0){{u+}
(或者
list.foldLeft(0)({{u+})
,如果您想更加明确的话)


但是,如果您添加
case
,您会得到一个分部函数,而不是一个函数,Scala不会为分部函数推断大括号,因此
list.map(case x=>x*2)
不起作用,但
list.map({case x=>2*2})
list.map{case x=>x*2}
will.

这里有两种不同的规则和推论:首先,当参数是函数时,Scala推断大括号,例如在
list.map({u*2)
中推断大括号,它只是
list.map({u*2})
的较短形式。其次,Scala允许您跳过最后一个参数列表上的括号,如果该参数列表有一个参数并且它是一个函数,那么
list.foldLeft(0)({u+}
可以写成
list.foldLeft(0){{u+}
(或者
list.foldLeft(0)({{u+})
,如果您想更加明确的话)


但是,如果您添加
case
,您会得到一个分部函数,而不是一个函数,Scala不会为分部函数推断大括号,因此
list.map(case x=>x*2)
不起作用,但
list.map({case x=>2*2})
list.map{case x=>x*2}
will.

我曾经试着写过这篇文章,但最终还是放弃了,因为规则有些分散。基本上,你必须掌握窍门

也许最好将注意力集中在大括号和圆括号可以互换使用的地方:将参数传递给方法调用时。当且仅当方法需要单个参数时,可以用大括号替换圆括号。例如:

List(1, 2, 3).reduceLeft{_ + _} // valid, single Function2[Int,Int] parameter

List{1, 2, 3}.reduceLeft(_ + _) // invalid, A* vararg parameter
while (x < 10) { x += 1 }
然而,为了更好地掌握这些规则,您还需要知道更多

使用parens增加编译检查 Spray的作者推荐round Paren,因为它们增加了编译检查。这对于像Spray这样的DSL尤其重要。通过使用parens,你告诉编译器应该只给它一行;因此,如果你不小心给它两个或更多,它会抱怨。现在大括号不是这种情况——例如,如果您忘记了某个操作符,那么您的代码将被编译,您将得到意外的结果,并且可能很难找到一个bug。下面是精心设计的(因为这些表达是纯粹的,至少会给出一个警告),但强调了这一点:

method {
  1 +
  2
  3
}

method(
  1 +
  2
  3
)
第一个编译,第二个给出预期的
错误:')'但找到整数文本
。作者想写
1+2+3

有人可能会说,对于带有默认参数的多参数方法,情况类似;在使用参数时,不可能意外地忘记用逗号分隔参数

冗长 一个重要的,经常被忽略的关于冗长的注释。使用大括号不可避免地会导致冗长的代码,因为清楚地说明结束大括号必须在其自己的行上:

…右大括号紧跟在最后一行之后 函数的行

许多自动重新格式化程序(如IntelliJ)将自动为您执行此重新格式化。所以,尽可能地坚持使用圆括号

中缀符号 使用中缀表示法时,如
List(1,2,3)indexOf(2)
如果只有一个参数,可以省略括号,并将其写入
List(1,2,3)indexOf 2
。这不是点表示法的情况

还请注意,如果有一个参数是多标记表达式,如
x+2
a=>a%2==0
,则必须使用括号来指示表达式的边界

多元组 因为有时可以省略括号,所以元组有时需要额外的括号,如
((1,2))
,有时可以省略外括号,如
(1,2)
。这可能会引起混乱

功能/部分功能升
try {
    block
} catch {
    case pattern if guard => statements
    case pattern => statements
} finally {
    block
}
{
    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) }
2 + { 3 }             // res: Int = 5
val x = { 4 }         // res: x: Int = 4
List({1},{2},{3})     // res: List[Int] = List(1,2,3)
def foo(f: Int => Unit) = { println("Entering foo"); f(4) }
foo( x => println(x) )
foo({ x => println(x) })
foo({ println("Hey"); x => println(x) })
foo { println("Hey"); x => println(x) }
foo { x => println(x) }
val tupleList = List[(String, String)]()
// doesn't compile, violates case clause requirement
val filtered = tupleList.takeWhile( case (s1, s2) => s1 == s2 ) 
// block of code as a partial function and parentheses omission,
// i.e. tupleList.takeWhile({ case (s1, s2) => s1 == s2 })
val filtered = tupleList.takeWhile{ case (s1, s2) => s1 == s2 }

// curly braces omission, i.e. List(1, 2, 3).reduceLeft({_+_})
List(1, 2, 3).reduceLeft(_+_)
// parentheses omission, i.e. List(1, 2, 3).reduceLeft({_+_})
List(1, 2, 3).reduceLeft{_+_}
// not both though it compiles, because meaning totally changes due to precedence
List(1, 2, 3).reduceLeft _+_ // res1: String => String = <function1>

// curly braces omission, i.e. List(1, 2, 3).foldLeft(0)({_ + _})
List(1, 2, 3).foldLeft(0)(_ + _)
// parentheses omission, i.e. List(1, 2, 3).foldLeft(0)({_ + _})
List(1, 2, 3).foldLeft(0){_ + _}
// block of code and parentheses omission
List(1, 2, 3).foldLeft {0} {_ + _}
// not both though it compiles, because meaning totally changes due to precedence
List(1, 2, 3).foldLeft(0) _ + _
// error: ';' expected but integer literal found.
List(1, 2, 3).foldLeft 0 (_ + _)

def foo(f: Int => Unit) = { println("Entering foo"); f(4) }
// block of code that just evaluates to a value of a function, and parentheses omission
// i.e. foo({ println("Hey"); x => println(x) })
foo { println("Hey"); x => println(x) }

// parentheses omission, i.e. f({x})
def f(x: Int): Int = f {x}
// error: missing arguments for method f
def f(x: Int): Int = f x
method {
  1 +
  2
  3
}

method(
  1 +
  2
  3
 )
List(1, 2, 3).reduceLeft {
  _ + _
}