Scala之小括号和花括号(Parentheses & Crurly Braces)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bluishglc/article/details/52946575

尽管这是一个非常基础的问题,但是如果不仔细梳理一下,还是会导致在某些场景下误读代码。原因是Scala对这两兄弟的使用实在是太灵活了,甚至可以说有些“随便”,本文将况逐一讨论下两者在不同场景的使用方法和区别。本文原文出处: http://blog.csdn.net/bluishglc/article/details/52946575 严禁任何形式的转载,否则将委托CSDN官方维护权益!

在调用函数时

人们会笼统地说在函数调用时,小括号和花括号是通用的,但实际上,情况会复杂的多

如果你要调用的函数有两个或两个以上的参数,那么你只能使用“小括号”

请看下面的示例:

scala> var add = (x: Int,y: Int) => x + y
add: (Int, Int) => Int = <function2>

scala> add(1,2)
res0: Int = 3

scala> add{1,2}
<console>:1: error: ';' expected but ',' found.
add{1,2}
     ^

如果你要调用的函数只有单一参数,那么“通常”情况下小括号和花括号是可以互换的

请看下面的示例:

scala> var increase = (x: Int) => x + 1
increase: Int => Int = <function1>

scala> increase(10)
res0: Int = 11

scala> increase{10}
res1: Int = 11

在调用单一参数函数时,小括号和花括号虽然等效,但还是有差异的

如果使用小括号,意味着你告诉编译器:它只接受单一的一行,因此,如果你意外地输入2行或更多,编译器就会报错。但对花括号来说则不然,如果你在花括号里忘记了一个操作符,代码是可以编辑的,但是会得到出乎意料的结果,进而导致难以追踪的Bug. 看如下的例子:

scala> def method(x: Int) = {
     |     x + 1
     | }
method: (x: Int)Int

scala> method {
     |   1 +
     |   2
     |   3
     | }
<console>:14: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
         1 +
           ^
res14: Int = 4

scala> method(
     |   1 +
     |   2
     |   3
<console>:4: error: ')' expected but integer literal found.
  3
  ^

花括号的调用虽然有warning,但是可以编译通过,小括号的调用会编译报错,但是花括号版本的返回值4是一个超出预期的结果。注意,16-19行,1+2是一行,它们合在一起才是一个完整的表达式,3是独立的表达式,算第二行。

所以,在调用单一参数函数时,特别是高阶函数, 如果函数参数用一行可以表达,通常我们推荐还是使用小括号,这样我们可以借助编译器获得更好的错误检查。

在调用一个单一参数函数时,如果参数本身是一个通过case语句实现的 “偏函数”,你只能使用“花括号”

究其原因,我觉得scala对小括号和花括号的使用还是有一种“习惯上”的定位的:通常人们还是会认为小括号是面向单行的,花括号面向多行的。在使用case实现偏函数时,通常都会是多个case语句,小括号不能满足这种场合,只是说在只有一个case语句时,会让人产生误解,认为只有一行,为什么不使用case语句。

scala> val tupleList = List[(String, String)]()
tupleList: List[(String, String)] = List()

scala> val filtered = tupleList.takeWhile( case (s1, s2) => s1 == s2 )
<console>:1: error: illegal start of simple expression
val filtered = tupleList.takeWhile( case (s1, s2) => s1 == s2 )
                                    ^

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

作为表达式(expression)和语句块(code blocks)时

if you need declarations, multiple statements, an import or anything like that, you need curly braces. And because an expression is a statement, parenthesis may appear inside curly braces. But the interesting thing is that blocks of code are also expressions, so you can use them anywhere inside an expression:

在非函数调用时,小括号可以用于界定表达式,花括号可以用于界定代码块。代码块由多条语句(statement)组成,每一条语句可以是一个”import”语句,一个变量或函数的声明,或者是一个表达式(expression),而一个表达式必定也是一条语句(statement),所以小括号可能出现在花括号里面,同时,语句块里可以出现表达式,所以花括号也可能出现在小括号里。看看下面的例子:

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... - 你懂的。。。。

没有更多推荐了,返回首页