3

I am trying to understand the exact details of when eta expansion happens and when param placeholders are expanded.

Going through many examples and SO answers/questions i understand the following:

val xs = (1 to 5)

/*ex1*/ xs.foreach(println)

/*ex2*/ xs.foreach(println _) // eta expansion?

/*ex3*/ xs.foreach(println(_)) // placeholder syntax

/*ex4*/ xs.foreach(println(_ * 2)) // INVALID -> xs.foreach(println(x => x * 2))

/*ex5*/ xs.foreach(Console.println _ * 2) // INVALID same reason?

/*ex6*/ xs.foreach(Console println _ * 2) // works

My quesion is: why does ex6 work?

jen
  • 357
  • 2
  • 10

1 Answers1

3
/*ex5*/ xs.foreach(Console.println _ * 2) // INVALID same reason?
/*ex6*/ xs.foreach(Console println _ * 2) // works

We can try to construct the function value inside foreach (ex6):

val fun1: Int => Unit = x => Console println x * 2
val fun2: Int => Unit =      Console println _ * 2 // short form

Note that using infix syntax, Scala would expect exactly one argument to the right, so how comes that x * 2 is (correctly) interpreted as a single argument? This is because the * symbol has higher precedence in the infix notation. If we used an alphabetical method, it would not work:

val fun6: Int => Unit = x => Console println x max 2  // not allowed

So while ex6 works, we can't however write (ex5):

val fun3: Int => Unit = x => Console.println x * 2

Simply because that is not valid Scala syntax:

Console.println 3  // not possible, either infix or parentheses!

So we would have to introduce parentheses:

val fun4: Int => Unit = x => Console.println (x * 2)

But with the extra parentheses, you cannot use the underscore shortcut:

val fun5: Int => Unit =      Console.println (_ * 2)

(for the same reason of ex4).

0__
  • 66,707
  • 21
  • 171
  • 266
  • Thanks! very well explained – jen Jan 13 '17 at 15:32
  • 2
    @jen P.S. Looking at it again, there is indeed another tricky bit that makes `fun1` and `fun2` work, that is the precedence of the symbolic operator `*` which I am just seeing now. For example `x => Console println x max 2` does _not_ work. – 0__ Jan 13 '17 at 15:42
  • I just figured that out as well. In this case it is really better to use parenthesis. I am also wondering if there is really no way to make this work without infix (placeholders without infix). My gut feelings tells me impossible – jen Jan 13 '17 at 15:47