Why this { } is omitted in the function literal definition?

Hi,
when I was reading some code of others, I found that the { } is omitted when they define a function literal and call a function with one function parameter. the code is like this bellow:

def test(fun:()=>Unit)=fun()
test {()=>
val str=“hahaha”
println(str)
}

the code above can work well. but why it’s not like this bellow?

def test(fun:()=>Unit)=fun()
test {()=>{
val str=“hahaha”
println(str)}
}

because when I define a function with multi lines, the { } can not be omitted, just like:
val fun=()=>{ val str=“hahaha”
println(str)}
}
so just confused. can anyone explain something?

1 Like

Why this { } is omitted in the function literal definition?

Sugar syntax.

test { ()=>
  val str = "hahaha"
  println(str)
}

Is enough, it is sugar syntax for:

test({ ()=> {
  val str = "hahaha"
  println(str)
}})

{} defines a block of code that can contain multiple statements and has a value equal to the last expression in it. Normally, arguments to functions are passed with (). However, when there is a single argument in a list, you are allowed to use {} instead of (). This is true whether the argument is a function or just some value. For example,

scala> math.sqrt{9}
val res0: Double = 3.0

While people wouldn’t generally use {} for that situation, the general ability to use {} instead of () for any argument list with a single argument comes in handy in many situations. It is used mostly when the argument is a function, as you are seeing in your example, but also in any place where you want to have multiple statements in an argument. This supports the DSL aspects of Scala, especially when used with pass-by-name arguments.

test({ ()=> {
  val str = "hahaha"
  println(str)
}})

hello,why in this form, the “{” after “=>” can be omitted? do you have any more docs or books or tutorials mentioned this? thanks.

1 Like

Uhm, not really sure where all the sugar syntax of the language is documented, you just learn it with time.

oh oh, thanks again

I will note that the first rule is one that I learned reading “Programming in Scala” by Odersky et al. years ago. The second one I only learned through experience. Scala accepts { args => ... } as a function block. I have to admit that I find it very useful in many situations. I expect that it is closely related to the partial function syntax.

{ 
    case pattern1 => ...
    case pattern2 => ...
    ...
}

It is basically like a partial function with only one case so the case keyword is omitted.

so scala really holds some opaque tricks or sugars for a new comer, especially when someone can not find this trick in any book or tutorial but only from forum or blog.

1 Like

yo totally agree, I’m exactly 14 days into my scala studies and the overall experience is analogous to peeling an onion

you cry at first, but each layer of the scala onion reveals some new discovery and allows the hidden parts to emerge

I would say the specialization on coursera has been a life saver vs just reading the docs like one would perhaps normally do

1 Like

Maybe newcomers should just avoid these kinds of “opaque tricks or sugars” altogether if they don’t understand them. I’ve been using Scala for many years, and I rarely if ever need these kinds of tricks. I always try to use the simplest and most straightforward syntax possible in any particular case.

this is true and a good practice. In fact I am doing so, but sometimes I have to read others’ code and that’s why I have this question.

1 Like

That happens all the time to me, too. Especially in the more advanced code around the FP libraries.

So, I wonder if there is a website somewhere collecting and documenting all of these different “syntatic sugar equivalencies”?

It sure would help those of us who don’t use Scala 40 hours a week and remain fully aware of every possible valid expression variation. It would give us a place to peruse these patterns to better understand how to parse them.

Even better would be a tool which worked to reverse these compressed expressions. The idea is that something like…

object Phase extends ((Int, String) => Phase) { ... }

is equivalent to…

object Phase extends Function2[Int, String, Phase] { ... }

There are literally hundreds of variations throughout Scala, getting even worse in Scala 3, that makes newcomers and those who never come to use Scala fulltime more likely to drift away with the vague reinforcement that “Scala is over complex”. When really, Scala is super awesomely expressive, but just doesn’t have good documentation support in an important, but not urgent, area of growing to learn the language.

To meta up, are there any efforts to define, roadmap, and address this area?

I keep a semi categorized (by heading levels) scala syntax cheatsheet on github

2 Likes

I understand your concern. One of my pet peeves has always been the use of advanced programming features when simpler ones are sufficient. As far as I am concerned, the most important thing to know about the advanced features of any language is not how to use but when to use them.

1 Like

I couldn’t agree more.