4

As far as I know, the infix operator usage in Scala should be equivalent to the invocation of a method. So:

scala> "a" + 3.toString
res0: java.lang.String = a3

Is the same as:

scala> "a".+(3.toString) 
res1: java.lang.String = a3

I came across an occasion where this is not happening, when there is a placeholder. I was doing something more complex, but it can be distilled to:

scala> def x(f:(Int)=>String) = f(3)
x: (f: Int => String)String
scala> x("a" + _.toString)
res3: String = a3

So far so good. But...

scala> x("a".+(_.toString))
<console>:9: error: missing parameter type for expanded function ((x$1) => x$1.toString)
          x("a".+(_.toString))

What's the difference here? What am I missing?

Jordi

agile_jordi
  • 113
  • 4
  • 2
    possible duplicate of [Scala foreach strange behaviour](http://stackoverflow.com/questions/2173373/scala-foreach-strange-behaviour) – kiritsuku Jul 03 '12 at 12:58
  • 5
    Well, the _answer_ is a duplicate, but how would anyone know that from the question? I think answers to this question ought to link related questions, instead of closing the question itself. – Daniel C. Sobral Jul 03 '12 at 15:06

2 Answers2

11

The _ placeholder can only appear at the topmost Expr in its function. That means

(_.toString)

is itself a function, and "a" + some function of unknown type doesn't make much sense to the compiler.

jpalecek
  • 47,058
  • 7
  • 102
  • 144
  • Thanks! So I understand that whether you can use _ or not depends on the expression you are trying to express. I could filter a collection of ints using col.filter(_+2*3<10) but I couldn't do col.filter((_+2)*3<10), cause (_+2) would be a function itself. So, in the second example, I would need to rewrite it not to use parenthesis o not to use _. – agile_jordi Jul 04 '12 at 15:32
10

Your assessment of infix notation is correct, but your understanding of placeholder parameters is flawed.

When you use underscore as a placeholder parameter, you are creating a function. The question is what are the boundaries of that function: where does it start, where does it end? For example, consider this expression:

_ + _ + _

How should it be translated? Here are some alternatives:

(x, y, z) => { x + y + z }
(x, y) => { (z) => { x + y } + z }
(x) => { x + { (y, z) => y + z } }

Well, Scala rule is that the scope is the innermost parenthesis-delimited expression, or the whole expression otherwise. So, in practice, you wrote two different things:

x("a" + _.toString) // is the same thing as
x((y) => "a" + y.toString)

x("a".+(_.toString)) // is the same thing as
x("a".+((y) => y.toString))
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • Thank you very much for your answer! But what I find surprising is that it depends on parenthesis instead of depending on the AST that results. Both expressions I used yeld the same AST. But the behavior of _ depends on parenthesis. That confused me. – agile_jordi Jul 04 '12 at 15:29
  • @user1207633 It's obviously not the same AST, since it doesn't even parse the same way. Look at the grammar -- there's an EBNF available on the language specification. – Daniel C. Sobral Jul 04 '12 at 18:57