27

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 _?

hammar
  • 138,522
  • 17
  • 304
  • 385
Senthess
  • 17,020
  • 5
  • 23
  • 28

3 Answers3

28

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>
Jean-Philippe Pellet
  • 59,296
  • 21
  • 173
  • 234
6

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 )    
paradigmatic
  • 40,153
  • 18
  • 88
  • 147
  • See also [Myth: methods and functions are the same thing](http://stackoverflow.com/questions/3926047/debunking-scala-myths/4812176#4812176). – Aaron Novstrup Jul 11 '11 at 18:47
4

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.

agilesteel
  • 16,775
  • 6
  • 44
  • 55