I noticed that when I'm working with functions that expect other functions as parameters, I can sometimes do this:
someFunction(firstParam,anotherFunction)
But other times, the compiler is giving me an error, telling me that I should write a function like this, in order for it to treat it as a partially applied function:
someFunction(firstParam,anotherFunction _)
For example, if I have this:
object Whatever {
def meth1(params:Array[Int]) = ...
def meth2(params:Array[Int]) = ...
}
import Whatever._
val callbacks = Array(meth1 _,meth2 _)
Why can't I have the code like the following:
val callbacks = Array(meth1,meth2)
Under what circumstances will the compiler tell me to add _
?
The rule is actually simple: you have to write the _
whenever the compiler is not explicitly expecting a Function
object.
Example in the REPL:
scala> def f(i: Int) = i
f: (i: Int)Int
scala> val g = f
<console>:6: error: missing arguments for method f in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
val g = f
^
scala> val g: Int => Int = f
g: (Int) => Int = <function1>
In Scala a method is not a function. The compiler can convert a method implicitly in a function, but it need to know which kind. So either you use the _
to convert it explicitly or you can give some indications about which function type to use:
object Whatever {
def meth1(params:Array[Int]): Int = ...
def meth2(params:Array[Int]): Int = ...
}
import Whatever._
val callbacks = Array[ Array[Int] => Int ]( meth1, meth2 )
or:
val callbacks: Array[ Array[Int] => Int ] = Array( meth1, meth2 )
In addition to what Jean-Philippe Pellet said, you can use partially applied functions, when writing delegate classes:
class ThirdPartyAPI{
def f(a: Int, b: String, c: Int) = ...
// lots of other methods
}
// You want to hide all the unnecessary methods
class APIWrapper(r: ThirdPartyAPI) {
// instead of writing this
def f(a: Int, b: String, c: Int) = r.f(a, b, c)
// you can write this
def f(a: Int, b: String, c: Int) = r.f _
// or even this
def f = r.f _
}
EDIT added the def f = r.f _
part.