2

I have two set methods defined as follows:

  def set(value: Any) : Unit = {
    val (a, b, c, d) = value.asInstanceOf[(Int, Int, Int, Int)]
    set(a, b, c, d)
  }
  def set(aValue: Int, bValue: Int, cValue: Int, dValue: Int) = {
    ...
  }

I also have a method that generates a tuple:

def getResults() = (1,2,3,4)

I would like to give the getResults() as an input to the set method.

((set _).tupled)(getResults())

The issue is that this code does not compile as set is defined twice. How can I resolve this issue?

enter image description here

samthebest
  • 30,803
  • 25
  • 102
  • 142
prosseek
  • 182,215
  • 215
  • 566
  • 871
  • 9
    [Don't overload method names?](http://stackoverflow.com/a/2512001/334519) – Travis Brown Aug 14 '14 at 19:50
  • 2
    Your code works for me. Are you sure you are not just falling for a presentation compiler problem in Eclipse? – 0__ Aug 14 '14 at 19:58
  • It seems it depends on definition order, if `set(aValue:Int, bValue:Int, cValue:Int, dValue:Int)` is the last, then it works. – cchantep Aug 14 '14 at 20:03
  • You code is working correctly ! – faissalb Aug 14 '14 at 20:10
  • 1
    coming from java a while back i had similar problems and i realised after reading and experimenting that method overloading in scala works differently and it should be avoided : http://stackoverflow.com/questions/2510108/why-avoid-method-overloading – firephil Aug 14 '14 at 22:26
  • @firephil: I'm not sure I'd say that method overloading works _differently_ in Scala—it's more that it interacts with Scala features that Java doesn't have in ways that aren't always very nice. – Travis Brown Aug 15 '14 at 00:36
  • Avoid designs that result in `asInstanceOf` – samthebest Aug 15 '14 at 09:54

1 Answers1

3

The presentation compiler of your IDE appears to be more confused than it should be. If you try the code in a REPL it will work. Unfortunately, though, the resolution of set depends on the definition order.

Here's a scala REPL session demonstrating this fact:

scala> :paste
// Entering paste mode (ctrl-D to finish)

def set(value: Any) : Unit = {
    val (a, b, c, d) = value.asInstanceOf[(Int, Int, Int, Int)]
    set(a, b, c, d)
  }

 def set(aValue: Int, bValue: Int, cValue: Int, dValue: Int) = println("ok")

// Exiting paste mode, now interpreting.

set: (value: Any)Unit <and> (aValue: Int, bValue: Int, cValue: Int, dValue: Int)Unit
set: (value: Any)Unit <and> (aValue: Int, bValue: Int, cValue: Int, dValue: Int)Unit

scala> (set _).tupled((1, 2, 3, 4))
ok

scala> :paste
// Entering paste mode (ctrl-D to finish)

 def set(value: Any) : Unit = {
    val (a, b, c, d) = value.asInstanceOf[(Int, Int, Int, Int)]
    set(a, b, c, d)
  }

// Exiting paste mode, now interpreting.

set: (value: Any)Unit

scala> (set _).tupled((1, 2, 3, 4))
<console>:9: error: value tupled is not a member of Any => Unit
              (set _).tupled((1, 2, 3, 4))

Generally speaking, the confusion comes from overloading mixed with partially applied function.

Overloaded methods are disambiguated using their parameter list, but, when you partially apply them, you're throwing this information away, and you can only hope that the compiler will see the "right" set before the wrong one.

However, I doubt this is specified anywhere, so you're basically binding the semantic of your program to a compiler implementation detail: bad idea, isn't it?

As Travis Brown already suggested in the comments, why don't you just avoid overloading and make your life (and the compiler) happier?

Community
  • 1
  • 1
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235