2

Getting to know scala better, I came across a behaviour I cannot explain. The below code works fine:

def triple(x: Double) = 3 * x
Array(3.14,1.42,3.9).map(triple)

However, If I call the scala ceil function in math library then I will need to pass an _ for it to work

def valueAtOneQuarter(f: (Double)=> Double) = f(0.25)
valueAtOneQuarter(sqrt _)

What is special about the _ in this context from the function call in the earlier piece of code.

jtkSource
  • 675
  • 9
  • 21

3 Answers3

3

The underscore is actually expanded to a function.

So sqrt _ gets turned into the function a => sqrt(a).

You will notice that this expanded function matches the parameter type f of the valueatonequarter method.

In more general terms, the underscore is sometimes needed to flag to the compiler to turn the method (a method is declared using def) into a function (methods and functions are similar but not the same thing). The compiler will attempt to automatically convert the method to a function for you but in some cases it needs additional pointers (like an explicit type declaration or _). See here for a full explanation of eta expansion and partial functions: https://medium.com/@sinisalouc/on-method-invocations-or-what-exactly-is-eta-expansion-1019b37e010c

jsdeveloper
  • 3,945
  • 1
  • 15
  • 14
  • This does not answer the question why it requires underscore in one case, but not in the other. – Dima Jun 24 '17 at 12:26
1

A method and a function are not the same in Scala.

You define a method this way:

def method(x:Double):Double = ...

But you define a function using this way:

val func = (x: Double):Double => {...}

when you pass a function as a parameter to a method it must be a function, but not a method.

So you must use underscore to make a function from a method.

Sometimes Scala uses “Eta Expansion” capability to automatically convert the method into a function. But in some cases you must do it manually

  • Thanks seems _ has different meaning in different context in scala. its almost like if there was some gap _ is the answer – jtkSource Jun 24 '17 at 12:05
1

Answering since the existing answers don't really explain when _ is needed, just "sometimes" or "in some cases".

A very important concept to understand in Scala is expected type. In your first example the expected type for argument of map is Double => B with some unknown B; in the second it's Double => Double. When the expected type is a function type and a method name is passed, it'll be automatically converted to a function. So, as comments say, the second example works without _. It's only necessary where there is no expected type, say

val f = sqrt _

There can also be issues when the method is overloaded, but there just adding _ generally won't work either; instead, you'll specify the argument type to show which method is used, e.g. max(_: Int, _: Int) or max(_: Double, _: Double).

Thanks seems _ has different meaning in different context in scala

Yes, quite a few: What are all the uses of an underscore in Scala?

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487