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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With