0

Using scala 2.10, in scala REPL. I have two definitions of myf, which is overloaded using different argument type. But when I call myf(line 7), it calls def myf(data:List[Int]) instead of def myf(data:List[String]). Despite that the argument itself is of type dataString:List[String].

How do I call myf(data:List[String]) inside myf(data:List[Int]) ?

I tried to handle type erasure with (implicit d: DummyImplicit) as shown in here

def myf(data:List[String]) : Unit = {
    data.foreach(println)
}

def myf(data:List[Int])(implicit d: DummyImplicit) : Unit = {
    val dataString:List[String] = data.map(_ + 1000).map(_.toString)     // do something else before toString
    myf(dataString:List[String])      // want to call myf(data:List[String]), does not want to call myf(data:List[Int])
}

val d:List[Int] = List(1,2,3)
myf(d)

Errors to:

Name: Compile Error
Message: <console>:50: error: type mismatch;
 found   : List[String]
 required: List[Int]
           myf(dataString:List[String])      // want to call myf(data:List[String]), does not want to call myf(data:List[Int])
Sida Zhou
  • 3,529
  • 2
  • 33
  • 48
  • 1
    Why? "Why try to emulate something that can never work properly given JVM restrictions?" Why not just give the two functions two different names? Overloading based on parameter types is fickle enough already, especially with type erasure. A lot of pain for what gain exactly? – Thilo Apr 25 '19 at 06:51
  • 5
    This won't run in the REPL, or the IntelliJ worksheet, because each compilation unit is wrapped in its own `object`. Thus the 2nd definition of `myf()` masks the 1st. Your code runs fine when wrapped in an `object`, making the whole thing a compilation unit with 2 definitions of `myf()`. – jwvh Apr 25 '19 at 07:25
  • 1
    I'm indeed running in a REPL – Sida Zhou Apr 25 '19 at 07:51
  • @jwvh I've tried to write the same code in a .scala file with a main() method, it gives the same compilation error.. – Sida Zhou Apr 25 '19 at 09:33
  • @SidaZhou; I'm able to run your code, unaltered, in various ways: 1-Pasted as-is into the REPL via `:paste`. 2-Inside an `object` in an IDE worksheet. 3-In an `object` in a `.scala` file. In the last case only the last 2 lines of the posted code goes in the `main()` method. – jwvh Apr 25 '19 at 10:28
  • @jwvh Can you post the full code as an answer or as a gist? EDIT: I think I know what you mean now – Sida Zhou Apr 25 '19 at 10:51

1 Answers1

1

Here's a REPL session that runs your code.

ShellPrompt> scala  #a fresh REPL session
Welcome to Scala 2.12.7 (OpenJDK 64-Bit Server VM, Java 11.0.2).
Type in expressions for evaluation. Or try :help.

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

def myf(data:List[String]) : Unit = {
    data.foreach(println)
}

def myf(data:List[Int])(implicit d: DummyImplicit) : Unit = {
    val dataString:List[String] = data.map(_ + 1000).map(_.toString)     // do something else before toString
    myf(dataString:List[String])      // want to call myf(data:List[String]), does not want to call myf(data:List[Int])
}

val d:List[Int] = List(1,2,3)
myf(d)

// Exiting paste mode, now interpreting.

1001
1002
1003
myf: (data: List[String])Unit <and> (data: List[Int])(implicit d: DummyImplicit)Unit
myf: (data: List[String])Unit <and> (data: List[Int])(implicit d: DummyImplicit)Unit
d: List[Int] = List(1, 2, 3)

Here's a file-compile demonstration.

ShellPrompt> cat so.sc
object SO {
  def myf(data:List[String]) : Unit = {
    data.foreach(println)
  }

  def myf(data:List[Int])(implicit d: DummyImplicit) : Unit = {
    val dataString:List[String] = data.map(_ + 1000).map(_.toString)
    myf(dataString:List[String])
  }

  def main(args:Array[String]): Unit = {
    val d:List[Int] = List(1,2,3)
    myf(d)
  }
}
ShellPrompt> scalac so.sc -deprecation -explaintypes -feature -unchecked -Xlint -Ypartial-unification
ShellPrompt> scala SO
1001
1002
1003
ShellPrompt>
jwvh
  • 50,871
  • 7
  • 38
  • 64