views:

128

answers:

1

I'm a bit shaky on the rules as to when you need a _ after a method to use it as a function. For example, why is there a difference between Foo's and Nil's :: in the following?

def square(n: Int) = n * n  
object Foo { def ::(f: Int => Int) = f(42) }

// ...

scala> Foo.::(square)
res2: Int = 1764

scala> Nil.::(square) 
<console>:6: error: missing arguments for method square in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
   Nil.::(square)
          ^
scala> Nil.::(square _) 
res3: List[(Int) => Int] = List(<function1>)
+6  A: 

When you omit all parameters in a partially applied function expression, then you need to follow it with _ unless the compiler requires a function type in the place where you use it.

When you call the method :: on Foo, the compiler expects a type Int => Int for the parameter. So you can safely omit the underscore after square in that position.

However, the :: method on Nil can take a parameter of any type. So rather than assume that you meant to partially apply the function, it complains unless you make it absolutely explicit by adding _.

So those are the rules... I can't really enlighten you about why those are the rules; maybe somebody else who has better knowledge of the compiler, the type system, and the language design will be able to tell you why. But I assume that without these rules, there would be a danger of accidental ambiguity in many places.

Ben James
Thanks. Just found part of the Scala Language Spec which gives some justification for the "why", in the change notes for Scala 2.0: "The rules for implicit conversions of methods to functions (§6.25) have been tightened. Previously, a parameterized method used as a value was always implicitly converted to a function. This could lead to unexpected results when method arguments where forgotten. Consider for instance the statement below: show(x.toString)..."
Matt R