Usage of _ in scala lambda functions

Can anyone please explain me why I can do:

a.mapValues(_.size)

instead of

a.mapValues(x => x.size)

but I can't do

a.groupBy(_)

instead of a

a.groupBy(x => x)

Solution 1:

When you write a.groupBy(_) the compiler understands it as an anonymous function:

x => a.groupBy(x)

According to Scala Specifications §6.23, an underscore placeholder in an expression is replaced by a anonymous parameter. So:

  • _ + 1 is expanded to x => x + 1
  • f(_) is expanded to x => f(x)
  • _ is not expanded by itself (the placeholder is not part of any expression).

The expression x => a.groupBy(x) will confuse the compiler because it cannot infer the type of x. If a is some collection of type E elements, then the compiler expects x to be a function of type (E) => K, but type K cannot be inferred...

Solution 2:

It isn't easy to see it here:

a.groupBy(_)

But it's easier to see it in something like this:

a.mkString("<", _, ">")

I'm partially applying the method/function. I'm applying it to some parameters (the first and last), and leaving the second parameter unapplied, so I'm getting a new function like this:

x => a.mkString("<", x, ">")

The first example is just a special case where the sole parameter is partially applied. When you use underscore on an expression, however, it stands for positional parameters in an anonymous function.

a.mapValues(_.size)
a.mapValues(x => x.size)

It is easy to get confused, because they both result in an anonymous function. In fact, there's a third underscore that is used to convert a method into a method value (which is also an anonymous function), such as:

a.groupBy _