scala 什么时候可以省略括号、点、大括号、=(函数)等的精确规则是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1181533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 01:33:25  来源:igfitidea点击:

What are the precise rules for when you can omit parenthesis, dots, braces, = (functions), etc.?

syntaxscala

提问by Antony Stubbs

What are the precise rules for when you can omit (omit) parentheses, dots, braces, = (functions), etc.?

什么时候可以省略(省略)括号、点、大括号、=(函数)等的确切规则是什么?

For example,

例如,

(service.findAllPresentations.get.first.votes.size) must be equalTo(2).
  • serviceis my object
  • def findAllPresentations: Option[List[Presentation]]
  • votesreturns List[Vote]
  • mustand beare both functions of specs
  • service是我的对象
  • def findAllPresentations: Option[List[Presentation]]
  • votes回报 List[Vote]
  • mustbe都是规范的函数

Why can't I go:

为什么我不能去:

(service findAllPresentations get first votes size) must be equalTo(2)

?

?

The compiler error is:

编译器错误是:

"RestServicesSpecTest.this.service.findAllPresentations of type Option[List[com.sharca.Presentation]] does not take parameters"

“RestServicesSpecTest.this.service.findAllPresentations 类型 Option[List[com.sharca.Presentation]] 不带参数”

Why does it think I'm trying to pass in a parameter? Why must I use dots for every method call?

为什么它认为我试图传入一个参数?为什么我必须为每个方法调用使用点?

Why must (service.findAllPresentations get first votes size)be equalTo(2) result in:

为什么必须(service.findAllPresentations get first votes size)是 equalTo(2) 结果:

"not found: value first"

“未找到:价值第一”

Yet, the "must be equalTo 2" of (service.findAllPresentations.get.first.votes.size)must be equalTo 2, that is, method chaining works fine? - object chain chain chain param.

然而,“must be equalTo 2”的“must be equalTo 2” (service.findAllPresentations.get.first.votes.size)必须是equalTo 2,也就是说,方法链工作正常吗?- 对象链链链参数。

I've looked through the Scala book and website and can't really find a comprehensive explanation.

我浏览了 Scala 的书和网站,并没有真正找到全面的解释。

Is it in fact, as Rob H explains in Stack Overflow question Which characters can I omit in Scala?, that the only valid use-case for omitting the '.' is for "operand operator operand" style operations, and not for method chaining?

事实上,正如 Rob H 在 Stack Overflow 问题中解释的那样,我可以在 Scala 中省略哪些字符?,这是省略“。”的唯一有效用例 是用于“操作数运算符操作数”样式的操作,而不是用于方法链?

采纳答案by Antony Stubbs

Class definitions:

类定义:

valor varcan be omitted from class parameters which will make the parameter private.

val或者var可以从类参数中省略,这将使参数成为私有。

Adding var or val will cause it to be public (that is, method accessors and mutators are generated).

添加 var 或 val 将使其成为 public(即生成方法访问器和修改器)。

{}can be omitted if the class has no body, that is,

{}如果类没有主体,则可以省略,即

class EmptyClass


Class instantiation:

类实例化:

Generic parameters can be omitted if they can be inferred by the compiler. However note, if your types don't match, then the type parameter is always infered so that it matches. So without specifying the type, you may not get what you expect - that is, given

如果编译器可以推断出通用参数,则可以省略它们。但是请注意,如果您的类型不匹配,则始终推断类型参数以使其匹配。因此,如果不指定类型,您可能不会得到您所期望的 - 也就是说,给定

class D[T](val x:T, val y:T);

This will give you a type error (Int found, expected String)

这会给你一个类型错误(Int found,expected String)

var zz = new D[String]("Hi1", 1) // type error

Whereas this works fine:

而这工作正常:

var z = new D("Hi1", 1)
== D{def x: Any; def y: Any}

Because the type parameter, T, is inferred as the least common supertype of the two - Any.

因为类型参数 T 被推断为两者中最不常见的超类型 - Any。



Function definitions:

函数定义:

=can be dropped if the function returns Unit (nothing).

=如果函数返回 Unit(无),则可以删除。

{}for the function body can be dropped if the function is a single statement, but only if the statement returns a value (you need the =sign), that is,

{}如果函数是单个语句,则可以删除函数体,但前提是该语句返回一个值(您需要=符号),即,

def returnAString = "Hi!"

but this doesn't work:

但这不起作用:

def returnAString "Hi!" // Compile error - '=' expected but string literal found."

The return type of the function can be omitted if it can be inferred (a recursive method must have its return type specified).

如果可以推断出函数的返回类型,则可以省略该函数的返回类型(递归方法必须指定其返回类型)。

()can be dropped if the function doesn't take any arguments, that is,

()如果函数不接受任何参数,则可以删除,即,

def endOfString {
  return "myDog".substring(2,1)
}

which by convention is reserved for methods which have no side effects - more on that later.

按照惯例,它是为没有副作用的方法保留的——稍后会详细介绍。

()isn't actually dropped per se when defining a pass by nameparamenter, but it is actually a quite semantically different notation, that is,

()在定义按名称传递参数时,它本身实际上并没有被删除,但它实际上是一个语义上完全不同的符号,也就是说,

def myOp(passByNameString: => String)

Says myOp takes a pass-by-name parameter, which results in a String (that is, it can be a code block which returns a string) as opposed to function parameters,

说 myOp 接受一个按名称传递的参数,它产生一个字符串(也就是说,它可以是一个返回字符串的代码块),而不是函数参数,

def myOp(functionParam: () => String)

which says myOptakes a function which has zero parameters and returns a String.

它说myOp接受一个具有零参数的函数并返回一个字符串。

(Mind you, pass-by-name parameters get compiled into functions; it just makes the syntax nicer.)

(请注意,按名称传递的参数会被编译成函数;它只会使语法更好。)

()can be dropped in the function parameter definition if the function only takes one argument, for example:

()如果函数只接受一个参数,则可以在函数参数定义中删除,例如:

def myOp2(passByNameString:(Int) => String) { .. } // - You can drop the ()
def myOp2(passByNameString:Int => String) { .. }

But if it takes more than one argument, you must include the ():

但如果需要多个参数,则必须包含 ():

def myOp2(passByNameString:(Int, String) => String) { .. }


Statements:

声明:

.can be dropped to use operator notation, which can onlybe used for infix operators (operators of methods that take arguments). See Daniel's answerfor more information.

.可以删除以使用运算符表示法,它只能用于中缀运算符(带参数的方法的运算符)。有关更多信息,请参阅Daniel 的回答

  • .can also be dropped for postfix functions list tail

  • ()can be dropped for postfix operators list.tail

  • ()cannot be used with methods defined as:

    def aMethod = "hi!" // Missing () on method definition
    aMethod // Works
    aMethod() // Compile error when calling method
    
  • .也可以删除后缀函数列表尾部

  • ()可以删除后缀运算符 list.tail

  • ()不能与定义为的方法一起使用:

    def aMethod = "hi!" // Missing () on method definition
    aMethod // Works
    aMethod() // Compile error when calling method
    

Because this notation is reserved by convention for methods that have no side effects, like List#tail (that is, the invocation of a function with no side effects means that the function has no observable effect, except for its return value).

因为按照惯例,这个符号是为没有副作用的方法保留的,比如 List#tail(也就是说,调用一个没有副作用的函数意味着该函数没有可观察的效果,除了它的返回值)。

  • ()can be dropped for operator notation when passing in a single argument

  • ()may be required to use postfix operators which aren't at the end of a statement

  • ()may be required to designate nested statements, ends of anonymous functions or for operators which take more than one parameter

  • ()传入单个参数时,可以删除运算符符号

  • ()可能需要使用不在语句末尾的后缀运算符

  • ()可能需要指定嵌套语句、匿名函数的结尾或使用多个参数的运算符

When calling a function which takes a function, you cannot omit the () from the inner function definition, for example:

调用带有函数的函数时,不能从内部函数定义中省略 (),例如:

def myOp3(paramFunc0:() => String) {
    println(paramFunc0)
}
myOp3(() => "myop3") // Works
myOp3(=> "myop3") // Doesn't work

When calling a function that takes a by-name parameter, you cannot specify the argument as a parameter-less anonymous function. For example, given:

调用带有按名称参数的函数时,不能将该参数指定为无参数匿名函数。例如,给定:

def myOp2(passByNameString:Int => String) {
  println(passByNameString)
}

You must call it as:

您必须将其称为:

myOp("myop3")

or

或者

myOp({
  val source = sourceProvider.source
  val p = myObject.findNameFromSource(source)
  p
})

but not:

但不是:

myOp(() => "myop3") // Doesn't work

IMO, overuse of dropping return types can be harmful for code to be re-used. Just look at specification for a good example of reduced readability due to lack of explicit information in the code. The number of levels of indirection to actually figure out what the type of a variable is can be nuts. Hopefully better tools can avert this problem and keep our code concise.

IMO,过度使用删除返回类型可能对代码的重用有害。只需查看规范中的一个很好的示例,该示例就会因代码中缺乏明确的信息而降低可读性。实际找出变量类型的间接级别的数量可能很疯狂。希望更好的工具可以避免这个问题并保持我们的代码简洁。

(OK, in the quest to compile a more complete, concise answer (if I've missed anything, or gotten something wrong/inaccurate please comment), I have added to the beginning of the answer. Please note this isn't a language specification, so I'm not trying to make it exactly academically correct - just more like a reference card.)

(好吧,为了编译一个更完整、更简洁的答案(如果我遗漏了什么,或者有什么错误/不准确,请评论),我已经添加到答案的开头。请注意这不是一种语言规范,所以我不想让它在学术上完全正确 - 更像是一张参考卡。)

回答by Daniel C. Sobral

You seem to have stumbled upon the answer. Anyway, I'll try to make it clear.

你似乎偶然发现了答案。无论如何,我会尽量说清楚。

You can omit dot when using the prefix, infix and postfix notations -- the so called operator notation. While using the operator notation, and only then, you can omit the parenthesis if there is less than two parameters passed to the method.

您可以在使用前缀、中缀和后缀符号时省略点 - 所谓的运算符符号。在使用操作符表示法时,只有这样,如果传递给方法的参数少于两个,您才能省略括号。

Now, the operator notation is a notation for method-call, which means it can't be used in the absence of the object which is being called.

现在,操作符符号是method-call的符号,这意味着它不能在没有被调用对象的情况下使用。

I'll briefly detail the notations.

我将简要地详细说明这些符号。

Prefix:

字首:

Only ~, !, +and -can be used in prefix notation. This is the notation you are using when you write !flagor val liability = -debt.

只有~, !,+-可用于前缀表示法。这是您在编写!flag或时使用的符号val liability = -debt

Infix:

中缀:

That's the notation where the method appears between an object and it's parameters. The arithmetic operators all fit here.

这是方法出现在对象和它的参数之间的符号。算术运算符都适合这里。

Postfix (also suffix):

后缀(也是后缀):

That notation is used when the method follows an object and receives no parameters. For example, you can write list tail, and that's postfix notation.

当方法跟随一个对象并且不接收任何参数时,将使用该表示法。例如,您可以编写list tail,这是后缀表示法。

You can chain infix notation calls without problem, as long as no method is curried. For example, I like to use the following style:

您可以毫无问题地链接中缀符号调用,只要没有柯里化方法。例如,我喜欢使用以下样式:

(list
 filter (...)
 map (...)
 mkString ", "
)

That's the same thing as:

这与以下内容相同:

list filter (...) map (...) mkString ", "

Now, why am I using parenthesis here, if filter and map take a single parameter? It's because I'm passing anonymous functions to them. I can't mix anonymous functions definitions with infix style because I need a boundary for the end of my anonymous function. Also, the parameter definition of the anonymous function might be interpreted as the last parameter to the infix method.

现在,如果 filter 和 map 采用单个参数,为什么我在这里使用括号?这是因为我将匿名函数传递给他们。我不能将匿名函数定义与中缀样式混合使用,因为我的匿名函数的末尾需要一个边界。此外,匿名函数的参数定义可能被解释为中缀方法的最后一个参数。

You can use infix with multiple parameters:

您可以使用带有多个参数的中缀:

string substring (start, end) map (_ toInt) mkString ("<", ", ", ">")

Curried functions are hard to use with infix notation. The folding functions are a clear example of that:

Curried 函数很难与中缀表示法一起使用。折叠函数就是一个明显的例子:

(0 /: list) ((cnt, string) => cnt + string.size)
(list foldLeft 0) ((cnt, string) => cnt + string.size)

You need to use parenthesis outside the infix call. I'm not sure the exact rules at play here.

您需要在中缀调用之外使用括号。我不确定这里的确切规则。

Now, let's talk about postfix. Postfix can be hard to use, because it can never be used anywhere except the end of an expression. For example, you can't do the following:

现在,让我们谈谈 postfix。Postfix 可能很难使用,因为它永远不能用在除了表达式结尾之外的任何地方。例如,您不能执行以下操作:

 list tail map (...)

Because tail does not appear at the end of the expression. You can't do this either:

因为尾部没有出现在表达式的末尾。你也不能这样做:

 list tail length

You could use infix notation by using parenthesis to mark end of expressions:

您可以通过使用括号来标记表达式的结尾来使用中缀表示法:

 (list tail) map (...)
 (list tail) length

Note that postfix notation is discouraged because it may be unsafe.

请注意,不鼓励使用后缀表示法,因为它可能不安全

I hope this has cleared all the doubts. If not, just drop a comment and I'll see what I can do to improve it.

我希望这已经消除了所有的疑虑。如果没有,请发表评论,我会看看我能做些什么来改进它。

回答by Antony Stubbs

A collection of quotes giving insight into the various conditions...

一组报价,可以深入了解各种条件......

Personally, I thought there'd be more in the specification. I'm sure there must be, I'm just not searching for the right words...

就个人而言,我认为规范中会有更多内容。我确定一定有,我只是没有在寻找正确的词...

There are a couple of sources however, and I've collected them together, but nothing really complete / comprehensive / understandable / that explains the above problems to me...:

然而,有几个来源,我将它们收集在一起,但没有什么真正完整/全面/可以理解/可以向我解释上述问题......:

"If a method body has more than one expression, you must surround it with curly braces {…}. You can omit the braces if the method body has just one expression."

“如果一个方法体有多个表达式,你必须用大括号 {…} 把它括起来。如果方法体只有一个表达式,你可以省略大括号。”

From chapter 2, "Type Less, Do More", of Programming Scala:

来自Programming Scala 的第 2 章“Type Less, Do More”

"The body of the upper method comes after the equals sign ‘='. Why an equals sign? Why not just curly braces {…}, like in Java? Because semicolons, function return types, method arguments lists, and even the curly braces are sometimes omitted, using an equals sign prevents several possible parsing ambiguities. Using an equals sign also reminds us that even functions are values in Scala, which is consistent with Scala's support of functional programming, described in more detail in Chapter 8, Functional Programming in Scala."

“上层方法的主体在等号 '=' 之后。为什么是等号?为什么不只是花括号 {...},就像在 Java 中一样?因为分号、函数返回类型、方法参数列表,甚至是花括号有时会被省略,使用等号可以防止几种可能的解析歧义。使用等号还提醒我们,即使函数在 Scala 中也是值,这与 Scala 对函数式编程的支持是一致的,在第 8 章函数式编程中进行了更详细的描述斯卡拉。”

From chapter 1, "Zero to Sixty: Introducing Scala", of Programming Scala:

编程 Scala 的第 1 章“零到六十:介绍 Scala”

"A function with no parameters can be declared without parentheses, in which case it must be called with no parentheses. This provides support for the Uniform Access Principle, such that the caller does not know if the symbol is a variable or a function with no parameters.

The function body is preceded by "=" if it returns a value (i.e. the return type is something other than Unit), but the return type and the "=" can be omitted when the type is Unit (i.e. it looks like a procedure as opposed to a function).

Braces around the body are not required (if the body is a single expression); more precisely, the body of a function is just an expression, and any expression with multiple parts must be enclosed in braces (an expression with one part may optionally be enclosed in braces)."

"Functions with zero or one argument can be called without the dot and parentheses. But any expression can have parentheses around it, so you can omit the dot and still use parentheses.

And since you can use braces anywhere you can use parentheses, you can omit the dot and put in braces, which can contain multiple statements.

Functions with no arguments can be called without the parentheses. For example, the length() function on String can be invoked as "abc".length rather than "abc".length(). If the function is a Scala function defined without parentheses, then the function must be called without parentheses.

By convention, functions with no arguments that have side effects, such as println, are called with parentheses; those without side effects are called without parentheses."

“一个没有参数的函数可以不带括号声明,在这种情况下必须不带括号调用它。这提供了对统一访问原则的支持,这样调用者不知道该符号是一个变量还是一个没有括号的函数参数。

如果返回值(即返回类型不是Unit),则函数体前面带有“=”,但当类型为Unit(即看起来像过程)时,可以省略返回类型和“=”与函数相反)。

不需要围绕身体的大括号(如果身体是单个表达式);更准确地说,函数体只是一个表达式,任何具有多个部分的表达式都必须用大括号括起来(一个部分的表达式可以选择用大括号括起来)。”

“可以在没有点和括号的情况下调用具有零个或一个参数的函数。但是任何表达式都可以在其周围使用括号,因此您可以省略点并仍然使用括号。

并且由于您可以在任何可以使用括号的地方使用大括号,因此您可以省略点并放入可以包含多个语句的大括号中。

可以在没有括号的情况下调用没有参数的函数。例如,String 上的 length() 函数可以作为 "abc".length 而不是 "abc".length() 调用。如果函数是不带括号定义的 Scala 函数,则必须不带括号调用该函数。

按照惯例,没有参数有副作用的函数,例如 println,是带括号调用的;那些没有副作用的被称为没有括号。”

From blog post Scala Syntax Primer:

来自博客文章Scala Syntax Primer

"A procedure definition is a function definition where the result type and the equals sign are omitted; its defining expression must be a block. E.g., def f (ps) {stats} is equivalent to def f (ps): Unit = {stats}.

Example 4.6.3 Here is a declaration and a de?nition of a procedure named write:

"过程定义是一个函数定义,其中省略了结果类型和等号;它的定义表达式必须是一个块。例如,def f (ps) {stats} 等价于 def f (ps): Unit = {stats }.

例 4.6.3 下面是一个名为 write 的过程的声明和定义:

trait Writer {
    def write(str: String)
}
object Terminal extends Writer {
    def write(str: String) { System.out.println(str) }
}

The code above is implicitly completed to the following code:

上面的代码隐式补全为下面的代码:

trait Writer {
    def write(str: String): Unit
}
object Terminal extends Writer {
    def write(str: String): Unit = { System.out.println(str) }
}"

From the language specification:

从语言规范:

"With methods which only take a single parameter, Scala allows the developer to replace the . with a space and omit the parentheses, enabling the operator syntax shown in our insertion operator example. This syntax is used in other places in the Scala API, such as constructing Range instances:

“对于只接受一个参数的方法,Scala 允许开发人员用空格替换 . 并省略括号,从而启用我们插入运算符示例中显示的运算符语法。此语法用于 Scala API 的其他地方,例如作为构造 Range 实例:

val firstTen:Range = 0 to 9

Here again, to(Int) is a vanilla method declared inside a class (there's actually some more implicit type conversions here, but you get the drift)."

再一次,to(Int) 是一个在类中声明的普通方法(实际上这里有一些隐式类型转换,但你会得到偏差)。”

From Scala for Java Refugees Part 6: Getting Over Java:

来自Java 难民的 Scala 第 6 部分:克服 Java

"Now, when you try "m 0", Scala discards it being a unary operator, on the grounds of not being a valid one (~, !, - and +). It finds that "m" is a valid object -- it is a function, not a method, and all functions are objects.

As "0" is not a valid Scala identifier, it cannot be neither an infix nor a postfix operator. Therefore, Scala complains that it expected ";" -- which would separate two (almost) valid expressions: "m" and "0". If you inserted it, then it would complain that m requires either an argument, or, failing that, a "_" to turn it into a partially applied function."

"I believe the operator syntax style works only when you've got an explicit object on the left-hand side. The syntax is intended to let you express "operand operator operand" style operations in a natural way."

“现在,当您尝试“m 0”时,Scala 将其丢弃为一元运算符,理由是它不是一个有效的运算符(~、!、- 和 +)。它发现“m”是一个有效的对象——它是一个函数,而不是一个方法,所有的函数都是对象。

由于“0”不是有效的 Scala 标识符,因此它既不能是中缀也不能是后缀运算符。因此,Scala 抱怨它期望“;” -- 这将分隔两个(几乎)有效的表达式:“m”和“0”。如果你插入它,那么它会抱怨 m 需要一个参数,或者,如果失败,一个“_”将它变成一个部分应用的函数。”

“我相信运算符语法风格只有当你在左侧有一个显式对象时才有效。语法旨在让你以自然的方式表达“操作数运算符操作数”风格的操作。“

Which characters can I omit in Scala?

我可以在 Scala 中省略哪些字符?

But what also confuses me is this quote:

但同样让我困惑的是这句话:

"There needs to be an object to receive a method call. For instance, you cannot do “println “Hello World!”" as the println needs an object recipient. You can do “Console println “Hello World!”" which satisfies the need."

“需要有一个对象来接收方法调用。例如,你不能执行“println“Hello World!””,因为 println 需要一个对象接收者。可以做“Console println “Hello World!””,满足需要。

Because as far as I can see, there isan object to receive the call...

因为据我所看到的,一个对象接收呼叫...

回答by Mario Camou

I find it easier to follow this rule of thumb: in expressions spaces alternate between methods and parameters. In your example, (service.findAllPresentations.get.first.votes.size) must be equalTo(2)parses as (service.findAllPresentations.get.first.votes.size).must(be)(equalTo(2)). Note that the parentheses around the 2 have a higher associativity than the spaces. Dots also have higher associativity, so (service.findAllPresentations.get.first.votes.size) must be.equalTo(2)would parse as (service.findAllPresentations.get.first.votes.size).must(be.equalTo(2)).

我发现遵循这个经验法则更容易:在表达式中,空格在方法和参数之间交替。在您的示例中,(service.findAllPresentations.get.first.votes.size) must be equalTo(2)解析为(service.findAllPresentations.get.first.votes.size).must(be)(equalTo(2)). 请注意,围绕 2 的括号比空格具有更高的结合性。点也具有更高的关联性,因此(service.findAllPresentations.get.first.votes.size) must be.equalTo(2)将解析为(service.findAllPresentations.get.first.votes.size).must(be.equalTo(2)).

service findAllPresentations get first votes size must be equalTo 2parses as service.findAllPresentations(get).first(votes).size(must).be(equalTo).2.

service findAllPresentations get first votes size must be equalTo 2解析为service.findAllPresentations(get).first(votes).size(must).be(equalTo).2.

回答by Antony Stubbs

Actually, on second reading, maybe this is the key:

实际上,在二读中,也许这就是关键:

With methods which only take a single parameter, Scala allows the developer to replace the . with a space and omit the parentheses

对于只接受单个参数的方法,Scala 允许开发人员替换 . 带空格并省略括号

As mentioned on the blog post: http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6.

正如博客文章中提到的:http: //www.codecommit.com/blog/scala/scala-for-java-refugees-part-6

So perhaps this is actually a very strict "syntax sugar" which onlyworks where you are effectively calling a method, on an object, which takes one parameter. e.g.

因此,也许这实际上是一种非常严格的“语法糖”,它适用于您在对象上有效调用方法的情况,该方法采用一个参数。例如

1 + 2
1.+(2)

And nothing else.

没有别的。

This would explain my examples in the question.

这将解释我在问题中的例子。

But as I said, if someone could point out to be exactly where in the language spec this is specified, would be great appreciated.

但正如我所说,如果有人能指出在语言规范中具体指定的位置,将不胜感激。

Ok, some nice fellow (paulp_ from #scala) has pointed out where in the language spec this information is:

好的,一些好人(来自#scala 的 paulp_)指出了该信息在语言规范中的位置:

6.12.3: Precedence and associativity of operators determine the grouping of parts of an expression as follows.

  • If there are several infix operations in an expression, then operators with higher precedence bind more closely than operators with lower precedence.
  • If there are consecutive infix operations e0 op1 e1 op2 . . .opn en with operators op1, . . . , opn of the same precedence, then all these operators must have the same associativity. If all operators are left-associative, the sequence is interpreted as (. . . (e0 op1 e1) op2 . . .) opn en. Otherwise, if all operators are rightassociative, the sequence is interpreted as e0 op1 (e1 op2 (. . .opn en) . . .).
  • Postfix operators always have lower precedence than infix operators. E.g. e1 op1 e2 op2 is always equivalent to (e1 op1 e2) op2.

The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. e op (e1, . . . ,en). This expression is then interpreted as e.op(e1, . . . ,en).

A left-associative binary operation e1 op e2 is interpreted as e1.op(e2). If op is rightassociative, the same operation is interpreted as { val x=e1; e2.op(x ) }, where x is a fresh name.

6.12.3:运算符的优先级和结合性决定了表达式各部分的分组如下。

  • 如果表达式中有多个中缀操作,则优先级较高的运算符比优先级较低的运算符绑定得更紧密。
  • 如果有连续的中缀操作 e0 op1 e1 op2 。. .opn en 与操作符 op1, . . . , opn 具有相同的优先级,那么所有这些运算符必须具有相同的结合性。如果所有运算符都是左结合的,则该序列被解释为 (. . . (e0 op1 e1) op2 . . .) opn en。否则,如果所有运算符都是右结合的,则序列被解释为 e0 op1 (e1 op2 (. . .opn en) . . )。
  • 后缀运算符的优先级始终低于中缀运算符。例如 e1 op1 e2 op2 总是等价于 (e1 op1 e2) op2。

左关联运算符的右侧操作数可能由括在括号中的几个参数组成,例如 e op (e1, . . ,en)。然后这个表达式被解释为 e.op(e1, . . ,en)。

左关联二元运算 e1 op e2 被解释为 e1.op(e2)。如果 op 是右结合的,同样的操作被解释为 { val x=e1; e2.op(x ) },其中 x 是一个新名称。

Hmm - to me it doesn't mesh with what I'm seeing or I just don't understand it ;)

嗯 - 对我来说它与我所看到的不相符,或者我只是不明白它;)

回答by user92983

There aren't any. You will likely receive advice around whether or not the function has side-effects. This is bogus. The correction is to not use side-effects to the reasonable extent permitted by Scala. To the extent that it cannot, then all bets are off. Allbets. Using parentheses is an element of the set "all" and is superfluous. It does not provide any value once all bets are off.

没有。您可能会收到有关该功能是否有副作用的建议。这是假的。更正是在 Scala 允许的合理范围内不使用副作用。如果它不能,那么所有赌注都将取消。所有赌注。使用括号是集合“all”的一个元素,是多余的。一旦所有赌注结束,它就不会提供任何价值。

This advice is essentially an attempt at an effect systemthat fails (not to be confused with: is less useful than other effect systems).

这个建议本质上是失败的效果系统的尝试(不要与:不如其他效果系统有用)。

Try not to side-effect. After that, accept that all bets are off. Hiding behind a de facto syntactic notation for an effect system can and does, only cause harm.

尽量不要产生副作用。在那之后,接受所有赌注都已关闭。隐藏在效果系统的事实上的句法符号后面可以而且确实只会造成伤害。