Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala function not passed by name with curly brackets (braces)

I would like to pass a function by name do something before its execution. Consider the following example:

class Runner {
  def apply(procedure: => Unit) = {
    println("running procedure")
    procedure
  }
}

new Runner()(println("procedure!")) // #1
new Runner(){println("procedure!")} // #2

The only difference between call #1 and #2 is in curly braces. While the first call outputs

running procedure
procedure!

as expected, in the second call only

procedure!

is printed.

It seems that when curly braces are used, the procedure is not passed by name but executed instead. Why are the curly and round brackets not interchangeable in this example?

like image 782
Mifeet Avatar asked Dec 19 '22 17:12

Mifeet


1 Answers

First statement:

new Runner()(println("procedure!")) // #1

In first case, when parenthesis are used, apply() method gets invoked and println("procedure!") is passed as argument. So the first statement is equivalent to:

new Runner().apply(println("procedure!"))

Hence the output is:

running procedure
procedure!

Second statement:

new Runner(){println("procedure!")} // #2

While in second case you are creating an anonymous class by extending Runner. So in second case statement println("procedure!") is executed as part of constructor but apply() is not invoked hence you see only

procedure!

as output.

Custom Control Structure

I suppose you intended to create custom control structure by using second statement (though for compiler, it's an anonymous class). If that is the case, you can use below syntax:

val runner = new Runner()
runner.apply {println("procedure!")}
// OR simply 
runner {println("procedure!")} // this is possible because apply() is defined for Runner
like image 181
justAbit Avatar answered Jan 07 '23 10:01

justAbit