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:
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:
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 of something
to pass as an argument to another call?map
, why did the Scala compiler not report the ambiguity as an error?foo.bar
as equivalent to foo.bar()
?I have filed a bug on the Scala issue tracker and the consensus seems to be that this behaviour is a bug. The compiler should have thrown an error about the ambiguous reference to "my.something".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With