Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: String "+" vs "++"

I am new to Scala and I have seen code for concatenating Strings in Scala like this:

"test " ++ "1"

And I have tested, and it is also written in Scala Doc

"test " + "1"

So my understanding is that + is like the Java String + but ++ is more powerful, can take in more types of parameters. Also ++ seems to be universal to other things like List. I want to know if my understanding is correct. and any other differences? When should one over another just for string concatenation?

like image 684
Junchao Gu Avatar asked Oct 12 '15 05:10

Junchao Gu


1 Answers

It helps to take a look in scala.Predef to see what exactly is going on.

If you check there, you see that String in Scala is just an alias for java.lang.String. In other words, the + method on a String gets translated into Java's + operator.

So, if a Scala String is just a Java String, how does the ++ method even exist, you might ask. (Well, I'd ask, at least.) The answer is that there's an implicit conversion from String to WrappedString provided by the wrapString method, which is also in Predef.

Notice that ++ takes any GenTraversableOnce instance and adds all of the elements in that instance to the original WrappedString. (Note that the docs incorrectly state that the method returns a WrappedString[B]. This has to be incorrect, because WrappedString doesn't take type parameters.) What you'll get back is either a String (if the thing you add is a Seq[Char]) or some IndexedSeq[Any] (if it's not).

Here are some examples:

If you add a String to a List[Char], you get a String.

scala> "a" ++ List('b', 'c', 'd')
res0: String = abcd

If you add a String to a List[String], you get an IndexedSeq[Any]. In fact, the first two elements are Chars, but the last three are Strings, as the follow-up call shows.

scala> "ab" ++ List("c", "d", "e")
res0: scala.collection.immutable.IndexedSeq[Any] = Vector(a, b, c, d, e)

scala> res0 map ((x: Any) => x.getClass.getSimpleName)
res1: scala.collection.immutable.IndexedSeq[String] = Vector(Character, Character, String, String, String)

Finally, if you add a String to a String with ++, you get back a String. The reason for this is that WrappedString inherits from IndexedSeq[Char], so this is a convoluted way of adding a Seq[Char] to a Seq[Char], which gives you back a Seq[Char].

scala> "abc" + "def"
res0: String = abcdef

As Alexey noted, neither of these is a very subtle tool, so you're probably better off using string interpolation or a StringBuilder unless there's a good reason not to.

like image 126
Todd O'Bryan Avatar answered Oct 13 '22 00:10

Todd O'Bryan