多行函数文字作为 Scala 中的参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13872196/
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 04:48:28  来源:igfitidea点击:

Multiline function literal as arguments in Scala

scalafunction-literal

提问by altcoder

I always wondered why sometimes with function literals we can ignore the curly brace even for multiple statements. To illustrate this, the syntax for a multiline function literal is to enclose the statements with curly braces. Like so,

我一直想知道为什么有时使用函数文字我们甚至可以忽略多个语句的大括号。为了说明这一点,多行函数文字的语法是用大括号将语句括起来。像这样,

val fl = (x: Int) => {
  println("Add 25 to "+x)
  x + 25
}

However, when you pass it to a single-argument function, you can ignore the required curly brace for the function literal.

但是,当您将其传递给单参数函数时,您可以忽略函数文字所需的花括号。

So for a given function f,

所以对于给定的函数 f,

def f( fl: Int => Int ) {
  println("Result is "+ fl(5))
}

You can call f() like this,

你可以这样调用 f(),

f( x=> {
  println("Add 25 to "+x)
  x + 25
})
-------------------------
Add 25 to 5
Result: 30

Or when you use curly braces instead of parenthesis in the function call, you can remove the inner curly braces from the function literal. So the following code will also work,

或者,当您在函数调用中使用大括号代替括号时,您可以从函数文字中删除内部大括号。所以下面的代码也可以工作,

f{ x=>
  println("Add 25 to "+x)
  x + 25
}

The above code is more readable and I notice that a lot of examples use this syntax. However, is there any special rule that I may have missed, to explain why this is working as intended?

上面的代码更具可读性,我注意到很多示例都使用这种语法。但是,是否有任何我可能遗漏的特殊规则来解释为什么这是按预期工作的?

回答by som-snytt

There are just a couple of simple syntax rules. The appendix of the spec is worth perusing.

只有几个简单的语法规则。规范的附录值得细读。

A function literal or anonymous function (6.23) will look like x => Expror x => Blockdepending on whether the context is an Expr or a ResultExpr, respectively.

函数文字或匿名函数 (6.23) 将分别看起来像x => Exprx => Block取决于上下文是 Expr 还是 ResultExpr。

A function application (6.6) will look like f(Expr, Expr)or f BlockExpr, i.e., f{ Block }. That is, a BlockExpr is just a sequence of block statements inside {...}.

函数应用程序 (6.6) 看起来像f(Expr, Expr)f BlockExpr,即f{ Block }。也就是说,一个 BlockExpr 只是里面的一个块语句序列{...}

When you call f(g), then g is an Expr, so as a function literal, x => Expr. The Expr can be a BlockExpr, x => { ... }.

当您调用 时f(g),g 是一个 Expr,因此作为函数文字,x => Expr. Expr 可以是 BlockExpr, x => { ... }

When you call f{ Block }, then f { x => ... }has the function literal in ResultExpr of a Block (which is just a sequence of statements, no braces required).

当您调用f{ Block }, 然后f { x => ... }在块的 ResultExpr 中有函数文字(这只是一个语句序列,不需要大括号)。

Here, it's obvious that the anon func is at the bottom of a block:

在这里,很明显 anon func 位于块的底部:

scala> def m(x: Int=>Int) = x(5)
m: (x: Int => Int)Int

scala> m {
     | val y = 7
     | x => // no brace
     | x+y+1
     | }
res0: Int = 13

回答by wleao

This is one of the things that make Scala beautiful to me.

这是使 Scala 对我来说很漂亮的原因之一。

The simple answer to your question is:

你的问题的简单答案是:

Parentheses ( ) are meant for single line constructions. For instance, this works:

括号 ( ) 用于单行结构。例如,这有效:

  def f(fl: Int => Int) {
    println("Result is " + fl(5))
  }

  f(
   x =>
    x + 25)

  f(x => x + 25) // single line

and curly braces { } are meant for multiline statements. For instance, this works:

和花括号 { } 用于多行语句。例如,这有效:

 f { 
   x =>
     println("Add 25 to " + x)
     x + 25
 }   

but this code doesn't work:

但此代码不起作用:

f ( 
  x =>
    println("Add 25 to " + x)
    x + 25
)

The compiler complains with the following message:

编译器抱怨以下消息:

value x is not a member of Unit possible cause: maybe a semicolon is missing before `value x'?

值 x 不是 Unit 的成员可能的原因:也许在“值 x”之前缺少分号?

If you add the semicolon, you'll get a syntax error caused by the unmatched parenthesis.

如果添加分号,则会出现由不匹配括号引起的语法错误。

If you try to do this:

如果您尝试这样做:

f { x => println("Add 25 to " + x) x + 25 }

The compiler will get back to you with the message:

编译器将回复您并显示以下消息:

value x is not a member of unit

Do you get that he is trying to find x as a member of unit. Like:

你知道他试图找到 x 作为单位的成员吗?喜欢:

f { println("Add 25 to " + x).x.+(25) }

Which is clearly wrong.

这显然是错误的。

If you add the inner curly braces, Like this:

如果添加内部花括号,像这样:

f ( 
  x => {
    println("Add 25 to " + x)
    x + 25 
  }
)

This will also work, but you still have a multiline statement that is signaled by the usage of the curly braces. So the compiler knows what you want there is to first print and then add 25 to x.

这也可以工作,但您仍然有一个多行语句,该语句由大括号的使用表示。所以编译器知道你想要什么,首先打印然后将 25 添加到 x。

I've been bitten before by those subtleties. Ever since, I've been paying attention to the way I code with those, because you'll code and read a lot of this when you're mainly using maps, flatMaps, foreachs, fors and currying.

我以前被那些微妙的东西咬过。从那以后,我一直在关注我用这些代码编写代码的方式,因为当您主要使用 map、flatMaps、foreachs、fors 和 currying 时,您将编写并阅读大量此类内容。

Cheers!

干杯!