Scala 中大括号和圆括号之间的正式区别是什么,何时应该使用它们? [英] What is the formal difference in Scala between braces and parentheses, and when should they be used?

查看:42
本文介绍了Scala 中大括号和圆括号之间的正式区别是什么,何时应该使用它们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What is the formal difference between passing arguments to functions in parentheses () and in braces {}?

我从Scala 编程中得到的感觉 这本书认为 Scala 非常灵活,我应该使用我最喜欢的那个,但我发现有些情况可以编译,而另一些则不能.

The feeling I got from the Programming in Scala book is that Scala's pretty flexible and I should use the one I like best, but I find that some cases compile while others don't.

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

For instance (just meant as an example; I would appreciate any response that discusses the general case, not this particular example only):

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

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

=> error: illegal start of simple expression

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

=> 很好.

推荐答案

我曾经尝试过写这个,但最后我放弃了,因为规则有点分散.基本上,您必须掌握它的窍门.

I tried once to write about this, but I gave up in the end, as the rules are somewhat diffuse. Basically, you’ll have to get the hang of it.

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

Perhaps it is best to concentrate on where curly braces and parenthesis can be used interchangeably: when passing parameters to method calls. You may replace parenthesis with curly braces if, and only if, the method expects a single parameter. For example:

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

List{1, 2, 3}.reduceLeft(_ + _) // invalid, A* vararg parameter

但是,您还需要了解更多信息才能更好地掌握这些规则.

However, there’s more you need to know to better grasp these rules.

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

The authors of Spray recommend round parens because they give increased compile checking. This is especially important for DSLs like Spray. By using parens you are telling the compiler that it should only be given a single line; therefore if you accidentally give it two or more, it will complain. Now this isn’t the case with curly braces – if for example you forget an operator somewhere, then your code will compile, and you get unexpected results and potentially a very hard bug to find. Below is contrived (since the expressions are pure and will at least give a warning), but makes the point:

method {
  1 +
  2
  3
}

method(
  1 +
  2
  3
)

第一个编译,第二个给出error: ')' expected but integer literal found.作者想写1 + 2 + 3.

The first compiles, the second gives error: ')' expected but integer literal found. The author wanted to write 1 + 2 + 3.

有人可能会争辩说它与带有默认参数的多参数方法类似;使用括号时不可能不小心忘记逗号分隔参数.

One could argue it’s similar for multi-parameter methods with default arguments; it’s impossible to accidentally forget a comma to separate parameters when using parens.

关于冗长的一个重要的经常被忽视的注释.由于 Scala 风格指南 明确指出右花括号必须在自己的行上:

An important often overlooked note about verbosity. Using curly braces inevitably leads to verbose code since the Scala style guide clearly states that closing curly braces must be on their own line:

... 右大括号紧跟在最后一个函数的行.

… the closing brace is on its own line immediately following the last line of the function.

许多自动重新格式化程序,如 IntelliJ,会自动为您执行此重新格式化.所以尽量坚持使用圆括号.

Many auto-reformatters, like in IntelliJ, will automatically perform this reformatting for you. So try to stick to using round parens when you can.

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

When using infix notation, like List(1,2,3) indexOf (2) you can omit parenthesis if there is only one parameter and write it as List(1, 2, 3) indexOf 2. This is not the case of dot-notation.

另请注意,当您有一个多标记表达式的单个参数时,例如 x + 2a =>;a % 2 == 0,必须用括号表示表达式的边界.

Note also that when you have a single parameter that is a multi-token expression, like x + 2 or a => a % 2 == 0, you have to use parenthesis to indicate the boundaries of the expression.

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

Because you can omit parenthesis sometimes, sometimes a tuple needs extra parenthesis like in ((1, 2)), and sometimes the outer parenthesis can be omitted, like in (1, 2). This may cause confusion.

Scala 有函数和部分函数字面量的语法.它看起来像这样:

Scala has a syntax for function and partial function literals. It looks like this:

{
    case pattern if guard => statements
    case pattern => statements
}

唯一可以使用 case 语句的其他地方是带有 matchcatch 关键字:

The only other places where you can use case statements are with the match and catch keywords:

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 需要一个函数,那么你得到的就是一个函数.如果它需要一个偏函数,你就会得到一个偏函数.如果两者都是预期的,则会给出关于歧义的错误.

You cannot use case statements in any other context. So, if you want to use case, you need curly braces. In case you are wondering what makes the distinction between a function and partial function literal, the answer is: context. If Scala expects a function, a function you get. If it expects a partial function, you get a partial function. If both are expected, it gives an error about ambiguity.

括号可用于制作子表达式.花括号可用于创建代码块(这不是函数字面量,因此要小心尝试像使用它一样使用它).一个代码块由多个语句组成,每个语句可以是一个导入语句、一个声明或一个表达式.它是这样的:

Parenthesis can be used to make subexpressions. Curly braces can be used to make blocks of code (this is not a function literal, so beware of trying to use it like one). A block of code consists of multiple statements, each of which can be an import statement, a declaration or an expression. It goes like this:

{
    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 或类似的东西,你需要花括号.并且因为表达式是一个语句,括号可能出现在花括号内.但有趣的是代码块也是表达式,所以你可以在表达式的任何地方使用它们:

So, 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:

( { var x = 0; while (x < 10) { x += 1}; x } % 5) + 1

因此,由于表达式是语句,而代码块是表达式,因此以下所有内容都是有效的:

So, since expressions are statements, and blocks of codes are expressions, everything below is valid:

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...

不能互换的地方

基本上,您不能将 {} 替换为 (),反之亦然.例如:

Where they are not interchangeable

Basically, you can’t replace {} with () or vice versa anywhere else. For example:

while (x < 10) { x += 1 }

这不是方法调用,所以你不能用任何其他方式编写它.好吧,您可以将大括号放在括号内作为条件,以及使用括号括号内作为代码块:

This is not a method call, so you can’t write it in any other way. Well, you can put curly braces inside the parenthesis for the condition, as well as use parenthesis inside the curly braces for the block of code:

while ({x < 10}) { (x += 1) }

所以,我希望这会有所帮助.

So, I hope this helps.

这篇关于Scala 中大括号和圆括号之间的正式区别是什么,何时应该使用它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆