Why parentheses are not required when partial function used as parameter in scala?


#1

I found that parentheses are not required when partial function used as parameter in Scala

val array = Array(2)

array.map(x => x + 1)
array.map { case x => x + 1 }

{ case x => x + 1 } defines a partial function here, so it should be array.map({ case x => x + 1 }) , but there are no parentheses.So what happend here? Is that syntactic sugar?


#2

It isn’t just partial functions. Any argument list that takes a single argument can use curly braces instead of parentheses. For example:

scala> def sqr(x: Double) = x*x
sqr: (x: Double)Double

scala> sqr{5}
res0: Double = 25.0

The real advantage of this is DSLs when you are passing argument by name. It is also helpful for both partial and complete functions that span more than one line. Without this, you would have to put parenthesis outside the curly braces for all such cases.


#3

for the same reason that

def foo(i: Int) = i.toString
foo { 7 } 

compiles:

{ case x => x + 1 } is a block expression, and block expressions can be used without parentheses for function application per the spec section 6.6: https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#function-applications


#4

This is also a consequence of x and {x} both being expressions that evaluate to x. You could call it by sqr({{{{{{5.0}}}}}}) as well.


#5

Thans a lot. Then I got another question.I created a method which need By-name parameters

  def twice(action: => Unit) = {
    action
    action
  }
twice(System.out.println("bar"))

compiles,but the following one dosen’t

  twice(
    System.out.println("bar")
    System.out.println("foo")
  )

In this case I need to add curly braces to make it statement

  twice {
    System.out.println("bar")
    System.out.println("foo")
  }

So is a single System.out.println("bar") a statement?
Why twice(System.out.println("bar")) compiles?


#6

System.out.println("bar") is an expression with type Unit. Your function twice only expects a single parameter, so your call with round braces won’t compile, as you have several expressions, where only one is required.

The curly braces group several expressions together into one expression, so this way you can use multiple lines. The result of the grouped expression is the last expression inside. In this case, println returns Unit, which has only a single instance, the empty tuple (). So your whole block also returns Unit, like a single println.


#7

I’ve slightly reworded and expanded crater2150’s post. Maybe it will help.

  1. Curly braces group any number of statements into one.
  2. Round braces placed closely around curly braces are optional, i.e. they are inferred anyway.
  3. Because of the above:
twice {
  statement1
  statement2
}

is equivalent to:

twice({
  statement1
  statement2
})

so it’s now obvious that twice here takes single statement that comes from grouping statements statement1 and statement2 into one using curly braces.