Lifu Huang Lifu Huang - 1 year ago 73
Scala Question

Underscore after function?


scala> def method(x: Int) = x
method: (x: Int)Int

scala> val func = (x: Int) => x
func: Int => Int = <function1>

Consider the following code:

scala> method _
res0: Int => Int = <function1>

scala> func(_)
res1: Int => Int = <function1>

scala> func _
res2: () => Int => Int = <function0>

I can understand that
is eta expansion and
is equivalent to lambda function
(x) => func(x)
. But I cannot figure out the output of
. Could anyone please explain that for me?

Answer Source

This is actually a bit tricky. First, let's see what happens outside REPL:

It doesn't work when func is a local variable:

object Main extends App {
  def foo() = {
    val f = (_: Int) + 1
    f _


[error] /tmp/rendereraEZGWf9f1Q/src/main/scala/test.scala:8: _ must follow method; cannot follow Int => Int
[error]     f _
[error]     ^

But if you put it outside def foo, it compiles:

object Main extends App {
  val f = (_: Int) + 1
  val f1 = f _


because f is both a field of Main and a method without arguments which returns the value of this field.

The final piece is that REPL wraps each line into an object (because Scala doesn't allow code to appear outside a trait/class/object), so

scala> val func = (x: Int) => x
func: Int => Int = <function1>    

is really something like

object Line1 {
  val func = (x: Int) => x
import Line1._
// print result

So func on the next line refers to Line1.func which is a method and so can be eta-expanded.