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

来源:互联网 发布:软件服务协会 编辑:程序博客网 时间:2024/05/07 01:29

  • 在调用函数时
    • 如果你要调用的函数有两个或两个以上的参数那么你只能使用小括号
    • 如果你要调用的函数只有单一参数那么通常情况下小括号和花括号是可以互换的
    • 在调用单一参数函数时小括号和花括号虽然等效但还是有差异的
    • 在调用一个单一参数函数时如果参数本身是一个通过case语句实现的 偏函数你只能使用花括号
  • 作为表达式expression和语句块code blocks时

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

在调用函数时

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

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

请看下面的示例:

scala> var add = (x: Int,y: Int) => x + yadd: (Int, Int) => Int = <function2>scala> add(1,2)res0: Int = 3scala> add{1,2}<console>:1: error: ';' expected but ',' found.add{1,2}     ^

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

请看下面的示例:

scala> var increase = (x: Int) => x + 1increase: Int => Int = <function1>scala> increase(10)res0: Int = 11scala> increase{10}res1: Int = 11

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

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

scala> def method(x: Int) = {     |     x + 1     | }method: (x: Int)Intscala> method {     |   1 +     |   2     |   3     | }<console>:14: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses         1 +           ^res14: Int = 4scala> 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 expressionval 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... - 你懂的。。。。
1 0