In the REPL, I define a function. Note the return type.
scala> def next(i: List[String]) = i.map {"0" + _} ::: i.reverse.map {"1" + _}
next: (i: List[String])List[java.lang.String]
And if I specify the return type as String
scala> def next(i: List[String]): List[String] = i.map {"0" + _} ::: i.reverse.map {"1" + _}
next: (i: List[String])List[String]
Why the difference? I can also specify the return type as List[Any], so I guess String is just a wrapper supertype to java.lang.String. Will this have any practical implications or can I safely not specify the return type?
This is a very good question! First, let me assure you that you can safely specify the return type.
Now, let’s look into it… yes, when left to inference, Scala infers
java.lang.String, instead of justString. So, if you look up “String” in the ScalaDoc, you won’t find anything, which seems to indicate it is not a Scala class either. Well, it has to come from someplace, though.Let’s consider what Scala imports by default. You can find it by yourself on the REPL:
The first two are packages — and, indeed,
Stringcan be found onjava.lang! Is that it, then? Let’s check by instantiating something else from that package:So, that doesn’t seem to be it. Now, it can’t be inside the
scalapackage, or it would have been found when looking up on the ScalaDoc. So let’s look insidescala.Predef, and there it is!That means
Stringis an alias forjava.lang.String(which was imported previously). That looks like a cyclic reference though, but if you check the source, you’ll see it is defined with the full path:Next, you might want to ask why? Well, I don’t have any idea, but I suspect it is to make such an important class a little less dependent on the JVM.