Multiline function literal as arguments in Scala

℡╲_俬逩灬. 提交于 2019-11-27 04:38:50

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 => Expr or x => Block depending on whether the context is an Expr or a ResultExpr, respectively.

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

When you call f(g), then g is an Expr, so as a function literal, x => Expr. The Expr can be a 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).

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

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

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

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'?

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:

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.

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.

Cheers!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!