Antti Vikman
Antti Vikman

Reputation: 107

Why in Scala function defined without empty parentheses doesn't behave like function?

Consider the following 2 objects

object TestObj1 {
  def testMethod = "Some text"
}

object TestObj2 {
  def testMethod() = "Some text"
}

and if I call those methods directly, they do what I expect

scala> TestObj1.testMethod
res1: String = Some text

scala> TestObj2.testMethod
res2: String = Some text

But now if we define following function

def functionTakingFunction(callback: () => String) {
  println("Call returns: " + callback())
} 

and try to call it, the method defined without () is not accepted.

scala> functionTakingFunction(TestObj1.testMethod)
<console>:10: error: type mismatch;
 found   : String
 required: () => String
              functionTakingFunction(TestObj1.testMethod)
                                              ^

scala> functionTakingFunction(TestObj2.testMethod)
Call returns: Some text

I also noticed that you can't call the TestObj1.testMethod using parentheses, since it already is a String. But what is causing this behavior?

Upvotes: 3

Views: 1575

Answers (3)

om-nom-nom
om-nom-nom

Reputation: 62835

You are not passing the method, you're invoking it and then passing its result into the call.

If you want to pass the method, you first have to convert it into a function, and pass that:

functionTakingFunction(TestObj1.testMethod _)

Here the testMethod is converted into a partially applied function (said to be "tied").

The reason you have to do that is because TestObj1.testMethod does not evaluate to function0 (which is what need to be passed to functionTakingFunction), but to a String because of the way it is declared (without parentheses).

It works on TestObj2 because the testMethod is defined with parentheses and thus just typing TestObj2.testMethod does not invoke it.

Upvotes: 9

Sudipta Deb
Sudipta Deb

Reputation: 1050

Here, you are not passing the function. What you are trying to do is evaluate TestObj1.testFunction and then pass that result to functionTakingFunction But if you see the definition of functionTakingFunction, it says clearly

def functionTakingFunction(callback: () => String)

means this function expects a function with Return Type as Unit. But TestObj1.testFunction is having no return type.

The difference between Unit Return Type and No Return Type is:

  • No Return Type means this method will not return anything
  • Unit Return Type means this method will return something which is having no meaningful value.

Hope it helps you now. Happy coding and enjoy Scala.

Upvotes: -1

monnef
monnef

Reputation: 4053

functionTakingFunction(TestObj1.testFunction) is called as functionTakingFunction("Some text") - it is evaluated rather than passed

Upvotes: 0

Related Questions