Excuse the long set-up. This question relates to, but is not answered by, Scala: ambiguous reference to overloaded definition - best disambiguation? .
I'm pretty new to Scala, and one thing that's throwing me off is that Scala both:
- Has first-class functions
- Calls functions when using object-dot notation without any parenthetical argument lists (as if the function were a property)
These two language features are confusing me. Look at the below code:
class MyClass { def something(in: String): String = { in + "_X" } def something: String => String = { case _ => "Fixed" } } val my = new MyClass() println(List("foo", "bar").map(my.something))
I would expect this to print List("foo_X", "bar_X")
by calling the something
prototype that matches the map
's required String => ?
argument. Instead, the output is List("Fixed", "Fixed")
- Scala 2.11 is invoking the no-argument something()
and then passing its return value to the map
.
If we comment out the second no-argument prototype of something
, the output changes to be the expected result, demonstrating that the other prototype is valid in context.
Adding an empty argument list to the second prototype (making it def something()
) also changes the behavior.
Changing the my.something
to my.something(_)
wakes Scala up to the ambiguity it was silently ignoring before:
error: ambiguous reference to overloaded definition, both method something in class MyClass of type => String => String and method something in class MyClass of type (in: String)String match argument types (String) println(List("foo", "bar").map(my.something(_)))
Even using the supposedly-for-this-purpose magic trailing underscore doesn't work:
val myFun: (String) => String = my.something _
This results in:
error: type mismatch; found : () => String => String required: String => String val myFun: (String) => String = my.something _
My questions:
- If I have
MyClass
exactly as written (no changes to the prototypes, especially not adding an empty parameter list to one of the prototypes), how do I tell Scala, unambiguously, that I want the first one-argument version ofsomething
to pass as an argument to another call? - Since there are clearly two satisfying arguments that could be passed to
map
, why did the Scala compiler not report the ambiguity as an error? - Is there a way to disable Scala's behavior of (sometimes, not always) treating
foo.bar
as equivalent tofoo.bar()
?