deprecating string addition operator

293 views
Skip to first unread message

Matthew Pocock

unread,
Sep 10, 2015, 8:38:46 AM9/10/15
to scala-user
Hi,

I no longer intentionally use the string + operator. Whenever concatenating strings, I now use string interpolation. So, rather than saying: `name + " " + familyName` I now always right something like s"$name $familyName". I find this a better coding style because a) it is obvious that this is all happening in string-land, b) it's much easier to read and reason about how spaces and other content are fusing into the final string.

So given that we have string interpolation that works, and that the string + operator is a continuing source of bugs and confusion, is there a compelling case for not deprecating it and encouraging all uses of + for string concatenation to move over to interpolation?

Matthew

--
Dr Matthew Pocock
Turing ate my hamster LTD

Integrative Bioinformatics Group, School of Computing Science, Newcastle University

skype: matthew.pocock
tel: (0191) 2566550

martin odersky

unread,
Sep 10, 2015, 8:48:41 AM9/10/15
to Matthew Pocock, scala-user
The only reason for not deprecating it that I can see is that usage of
`+' is still ubiquitous. In my opinion, if we deprecate something as
common as String `+' (or procedure syntax, which is similarly widely
used), we need to have tooling for automatic program rewriting place.
Otherwise we force all users to do a lot of busywork which they might
find annoying.

Cheers

- Martin
> --
> You received this message because you are subscribed to the Google Groups
> "scala-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to scala-user+...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Martin Odersky
EPFL

Dennis Haupt

unread,
Sep 10, 2015, 8:59:43 AM9/10/15
to Matthew Pocock, scala-user
kill it with fire
 
Gesendet: Donnerstag, 10. September 2015 um 14:38 Uhr
Von: "Matthew Pocock" <turingate...@gmail.com>
An: scala-user <scala...@googlegroups.com>
Betreff: [scala-user] deprecating string addition operator
--

Jon Pretty

unread,
Sep 10, 2015, 9:05:43 AM9/10/15
to martin odersky, Matthew Pocock, scala-user
Hi Matthew, Martin,

An alternative (more general) idea I thought about a while ago was to use an implicit to determine how string literals are interpreted.

So, every occurrence of a string literal, such as,

   val myString = "foobar"

would resolve and apply an implicit, hence

   val myString = implicitly[StringCreator].create("foobar")

(where the "foobar" in `create` is the traditional kind).

We would have an implicit `StringCreator` in `Predef`, which users could override with an import. We could implement `create` with a macro, and it could return any type, for example a new value class, say `MyString`, wrapping a "real" string. We could then redefine the selection of methods available on `MyString` so that `+` isn't available.

One problem I think we would need to work around is that we would probably want to create an implicit conversion from `MyString` to `String` so that our new type works everywhere a `String` does. But unfortunately, that implicit would bring the `+` methods back into play, which defeats most of the point...

Dennis's suggestion is also worthy of consideration.

Cheers,
Jon
Jon Pretty
Propensive Ltd
@propensive

Oliver Ruebenacker

unread,
Sep 10, 2015, 9:18:46 AM9/10/15
to Dennis Haupt, Matthew Pocock, scala-user

     Hello,

  Not sure. String concatenation is something a complete beginner would typically need to use in one of their first apps. Using + is nicely simple and well-known from other languages. Replacing it with something less known and less understandable increases the already high entry barrier.

     Best, Oliver
--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

Dennis Haupt

unread,
Sep 10, 2015, 9:20:00 AM9/10/15
to martin odersky, Matthew Pocock, scala-user
+ could first be deprecated. once it is taken out, there could be an implicit replacement that needs to be explicitly imported to keep the functionality up. that way, the code rewrite can be avoided.
that is how i would do it.
 
Gesendet: Donnerstag, 10. September 2015 um 14:48 Uhr
Von: "martin odersky" <martin....@epfl.ch>
An: "Matthew Pocock" <turingate...@gmail.com>
Cc: scala-user <scala...@googlegroups.com>
Betreff: Re: [scala-user] deprecating string addition operator

martin odersky

unread,
Sep 10, 2015, 9:20:04 AM9/10/15
to Oliver Ruebenacker, Dennis Haupt, Matthew Pocock, scala-user
On Thu, Sep 10, 2015 at 3:18 PM, Oliver Ruebenacker <cur...@gmail.com> wrote:
>
> Hello,
>
> Not sure. String concatenation is something a complete beginner would
> typically need to use in one of their first apps. Using + is nicely simple
> and well-known from other languages. Replacing it with something less known
> and less understandable increases the already high entry barrier.

But note that ++ would still be available.

- Martin
Martin Odersky
EPFL

Kevin Wright

unread,
Sep 10, 2015, 9:22:06 AM9/10/15
to Oliver Ruebenacker, Dennis Haupt, Matthew Pocock, scala-user
You explicitly call .toString, or use interpolation

I don't think either of these are beyond beginner level.

However...The pain of debugging something turning into a String when you didn't mean it to?  That's nasty at *any* level.
Kevin Wright
mail: kevin....@scalatechnology.com
gtalk / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright
steam: kev_lee_wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

Dennis Haupt

unread,
Sep 10, 2015, 9:22:50 AM9/10/15
to Oliver Ruebenacker, Matthew Pocock, scala-user
for that case, + could still exist but only accept beginner typical arguments (strings and numbers), and the left side has to be a string
 
Gesendet: Donnerstag, 10. September 2015 um 15:18 Uhr
Von: "Oliver Ruebenacker" <cur...@gmail.com>
An: "Dennis Haupt" <h-s...@gmx.de>
Cc: "Matthew Pocock" <turingate...@gmail.com>, scala-user <scala...@googlegroups.com>
Betreff: Re: [scala-user] deprecating string addition operator

Filippo De Luca

unread,
Sep 10, 2015, 9:46:46 AM9/10/15
to Dennis Haupt, Oliver Ruebenacker, Matthew Pocock, scala-user
I think, the main issue is not the + operator, but the implicit conversion to string.

my 2cents

Kevin Wright

unread,
Sep 10, 2015, 9:48:20 AM9/10/15
to Filippo De Luca, Dennis Haupt, Oliver Ruebenacker, Matthew Pocock, scala-user
Sure, but from the compiler's perspective, it's just an implicit conversion to something with the + operator.
That thing just happens to be a String

Filippo De Luca

unread,
Sep 10, 2015, 9:53:43 AM9/10/15
to Kevin Wright, Dennis Haupt, Oliver Ruebenacker, Matthew Pocock, scala-user
Oh yes indeed.

To be honest, when a was newbie (Not that I am still to much fair from that) it has caused a lot of issue with the collections, as it was not clear to me which of the collection defines the + which not.

So it is probably true that a newbie will expect to be able to write "Hello" + "World", but is also true that they will not expect a Seq to become a String.

Seth Tisue

unread,
Sep 10, 2015, 10:33:05 AM9/10/15
to scala-user
the ticket of record on this is https://issues.scala-lang.org/browse/SI-194 ; it has some discussion, and links to other mailing list discussions

Vlad Patryshev

unread,
Sep 10, 2015, 10:48:42 AM9/10/15
to Matthew Pocock, scala-user
First, it's not even an addition; it is not commutative, and pretty much misleading.
But... how can you entice java people if the'll have to learn one more thing before even starting.

Thanks,
-Vlad

--

Seth Tisue

unread,
Sep 10, 2015, 12:28:30 PM9/10/15
to scala-user
P.S. It would be great to have a proper SIP for this and not just a bunch of discussions scattered around the Internet. Someone want to write one? Even if it didn't fully go through until we had a code-rewriting tool, there's still a possibility of it happening sooner but behind a flag (`-Xfuture` or what have you).

Haoyi Li

unread,
Sep 10, 2015, 2:17:16 PM9/10/15
to Seth Tisue, scala-user
 Not sure. String concatenation is something a complete beginner would typically need to use in one of their first apps

Calling toString on things is not a big deal. 

>>> "Hello " + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
>>> "Hello " + str(1)
'Hello 1'

First, it's not even an addition; it is not commutative, and pretty much misleading.

Why must addition has to be commutative? 

e.g. Python and Ruby have defined + to just be "add stuff together" and it works with numbers, strings, and arrays, and I have seen zero confusion about commutativity. 

>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]

Generally, `+` does what everyone wants, v.s. in Scala where you have to arbitrarily use + and ++ for different things. Worse, some things (Strings) have both + and ++ doing the same things, some things like collections have both + and ++ doing different things, and others have only one of + or ++

On Thu, Sep 10, 2015 at 9:28 AM, Seth Tisue <se...@tisue.net> wrote:
P.S. It would be great to have a proper SIP for this and not just a bunch of discussions scattered around the Internet. Someone want to write one? Even if it didn't fully go through until we had a code-rewriting tool, there's still a possibility of it happening sooner but behind a flag (`-Xfuture` or what have you).

--

Simon Ochsenreither

unread,
Sep 11, 2015, 1:49:34 AM9/11/15
to scala-user
I was planning to do something in that direction, I already had some changes in that direction which I would need to dig out again. Just a warning to the other poor souls trying to attempt these things: The + thing is hardcoded in various places in the compiler, just removing the implicit is not enough.

If there was a SIP, I would probably propose to tackle all dangerous implicit conversions at once, including Int -> Float, Long -> Float, Int -> Double, Long -> Double.

The hardest part is not removing the conversions, but adding the settings so that people can switch it on/off in their scope. That's really really ugly, and a reason why I would like to minimize the amount of settings available.

Oliver Ruebenacker

unread,
Sep 11, 2015, 9:04:10 AM9/11/15
to Simon Ochsenreither, scala-user

     Hello,

  Before we deprecate String.+, we should find a nice simple intuitive alternative. Having to call Any.toString is ugly. Without it, String.++ won't work. String interpolation works in obscure ways, and has nasty side-effects (e.g. s"\") - I would consider it still experimental.

  How about C++-style?

  out << "The answer is " << 42 << "." << endl;

  out could be an output stream or string builder. << returns the left hand side (output stream or string builder), so it can be chained. << can also accept manipulators as arguments that affect how the output is formatted. endl is line-break.

     Best, Oliver


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kevin Wright

unread,
Sep 11, 2015, 9:09:23 AM9/11/15
to Oliver Ruebenacker, Simon Ochsenreither, scala-user
I'm mostly fine with being able to concatenate anything onto a string.  So this is generally okay:

"The answer is " + 42 + "."

The main gotchas occur is when the left-hand side is coerced:

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

If that's what you really want (and it almost never is), then you should be forced to do it explicitly:

Seq("a","b","c").toString + "d"

Rex Kerr

unread,
Sep 11, 2015, 9:53:27 AM9/11/15
to Oliver Ruebenacker, Simon Ochsenreither, scala-user
Personally, I find using the same symbol to mean "left shift" and "concatenation", while also implying a very strong directional component that concatenation doesn't really possess, is pretty far from "intuitive".

 --Rex

Oliver Ruebenacker

unread,
Sep 11, 2015, 10:00:51 AM9/11/15
to Rex Kerr, Simon Ochsenreither, scala-user

     Hello,

  It actually isn't concatenation, but subsequent adding of things to an output stream or string builder.

  We could use another operator if << isn't suitable. But the precedence and associativity should be such that

  out op "The answer is " op 42 op "." op endl

  is interpreted as:

  (((out op "The answer is ") op 42)  op ".") op endl

     Best, Oliver

Rex Kerr

unread,
Sep 11, 2015, 10:16:07 AM9/11/15
to Oliver Ruebenacker, Simon Ochsenreither, scala-user
You're using it for concatenation, except written as sequential addition to a builder.  That isn't what I'd call intuitive.

Plus, we already have exactly this in the Java StringBuilder:

scala> val sb = new java.lang.StringBuilder
sb: StringBuilder =

scala> sb append "The answer is " append 42 append "."
res5: StringBuilder = The answer is 42.

  --Rex

Oliver Ruebenacker

unread,
Sep 11, 2015, 10:33:09 AM9/11/15
to Rex Kerr, Simon Ochsenreither, scala-user

     Hello,

  Yes, exactly, a short-hand for StringBuilder.append, and the same methods made available for output streams.

  The first thing a noob will want to do is print stuff to the console.

  Then, if they really really want to concatenate Strings, they can use ++, and Any.toString

  Then, they can learn that the best way to concatenate Strings is using a StringBuilder and it is so convenient because it works just the same way as printing things to the console.

     Best, Oliver

Rex Kerr

unread,
Sep 11, 2015, 10:50:35 AM9/11/15
to Oliver Ruebenacker, Simon Ochsenreither, scala-user
Okay, but the simple intuitive way to print things is

  val fortytwo = 42
  print The answer is fortytwo.

or for the expert,

  print The answer is $fortytwo.

Adding all the complexities of dealing with builders is not the way to help.  Builders introduce state; you don't want to have to care about state.  You have to know if the result is available once, or cached.  You have to know what happens if you get the result of the builder and then try to add more to it.  You might need to know the differences between what happens with toString and result.

A streaming IO-type API doesn't even work with printing, because you generally are not thinking, "Okay, now I want to output 'The answer is ' to standard out, and now I want to output '42', and now I want to output a period."  Instead, you think, "My sentence is 'The answer is 42.', and I want to print it."  Forcing the user to think about outputting over and over again does not aid simplicity.  The focus should be on how the text is presented, not that it's going out somewhere.

That's why string interpolation is nice.

  s"The answer is $fortytwo."

It reads just like you want the output to be.  Concat with + is a distant second:

  "The answer is " + fortytwo + "."

And piping to a string builder puts even more focus in the wrong place (i.e. the mechanics, rather than the result):

  val sb = new StringBuilder append "The answer is " append fortytwo append "."
  sb.toString

It's good to have when you need to be concerned about the details of the build process, but most of the time you just want to type what your output ought to look like, and get the output that looks like that.

  --Rex



Oliver Ruebenacker

unread,
Sep 11, 2015, 12:56:03 PM9/11/15
to Rex Kerr, Simon Ochsenreither, scala-user

     Hello,

  I withdraw the argument that loss of simple String concatenation would make it hard for noobs to print to the console, because they can always fall back to simply:

scala> print("The answer is "); print(42); println(".")
The answer is 42.

  Apart from that, what is the most straight-forward way to output a series of objects a1, a2, a3, a4?

  (1) Output them one by one.

  (2) Explicitly convert the first one to String. Then, use that to implicitly convert all objects to Strings while concatenating them into one big String. Then, output the big String.

  (3) Use an obscure syntax that looks like Bash or Perl, where identifiers have dollar signs in front of them, except that it is Scala, where identifiers don't have dollar signs, or at least normally they don't, but here they do. Be prepared to occasionally use braces with the dollar signs, or triple-quotes instead of normal quotes.

     Best, Oliver

Rex Kerr

unread,
Sep 11, 2015, 1:17:52 PM9/11/15
to Oliver Ruebenacker, Simon Ochsenreither, scala-user
On Fri, Sep 11, 2015 at 9:55 AM, Oliver Ruebenacker <cur...@gmail.com> wrote:


  Apart from that, what is the most straight-forward way to output a series of objects a1, a2, a3, a4?

This isn't usually the goal.

Usually you want output to look like something, and create extra objects as necessary to make it happen.

   --Rex

ivan

unread,
Sep 11, 2015, 2:17:41 PM9/11/15
to scala-user
Hi all,

This would be problematic for the cases such as:

    collection.fold(init) ( _ + _ )

(any generic method taking a -> a -> a typed lambdas)

Cheers,
Ivan

Matthew Pocock

unread,
Sep 11, 2015, 2:32:23 PM9/11/15
to ivan, scala-user

This is exactly the sort of case were you don't want to accidentally be concatenating accidentally stringified objects.

--

Rex Kerr

unread,
Sep 11, 2015, 4:27:05 PM9/11/15
to Matthew Pocock, ivan, scala-user
You probably don't even want to be folding over collections of strings on purpose, because folding with _ + _ on strings is O(n^2), whereas adding to a builder is O(n).

  --Rex

ivan

unread,
Sep 11, 2015, 4:35:10 PM9/11/15
to scala-user, turingate...@gmail.com, ivan....@gmail.com
> You probably don't even want to be folding over collections of strings on purpose, because
> folding with _ + _ on strings is O(n^2), whereas adding to a builder is O(n).

The point here is not in the fold, it is used only as an example. The point is in the line below it.

Cheers,
Ivan

ivan

unread,
Sep 11, 2015, 4:36:48 PM9/11/15
to scala-user, ivan....@gmail.com
> accidentally be concatenating accidentally stringified objects.

I don't see this as a problem of + for strings. But of the "stringification".

Cheers,
Ivan

Rich Oliver

unread,
Sep 12, 2015, 1:35:03 PM9/12/15
to scala-user
For development we want speed and succinctness. A beginner is developing. They are developing their own skill and understanding of the language. They maybe evaluating the language to decide if it worth the further investment of their time. Ideally it should be fast and functional. But speed of development is the overwhelming priority, not correctness, or immutabilty. For development we need debug statements

def debug(args: Any *): Unit

This prints the file name and line number followed by the toStrings of all its args. in addition every object should have a debug member

x.debug
myInt.debug

which again prints file name, line number and toString of the object. I can't imagine how much time I've spent trying to find my println debugging messages.

Production code should prioritise preciseness and comprehensibly not speed of writing or succinctness. "Any" should be a very rare parameter type in our production code signatures. Any, AnyRef, AnyVal should never be inferred by the compiler. Nor should type unons. Who writes code with:

val myList = List(5, 8.0, "A string", myClass1"

anyway. If for some reason they do, they should always have to explicitly define the type. Its a minuscule amount of effort to give the rest of us type safety for the other 99% of the time. And while I'm on one, 'match' should have type annotation.

Jeffrey Shaw

unread,
Sep 13, 2015, 10:31:42 AM9/13/15
to scala-user, turingate...@gmail.com
Creating tooling sounds like a lot of effort when replacing

" + "

with

" ++ "

will catch 99% of the uses of +. A more sophisticated search could ignore those strings inside strings and not replace them, but that's icing on the cake.

On Thursday, September 10, 2015 at 8:48:41 AM UTC-4, martin wrote:
The only reason for not deprecating it that I can see is that usage of
`+' is still ubiquitous. In my opinion, if we deprecate something as
common as String `+' (or procedure syntax, which is similarly widely
used), we need to have tooling for automatic program rewriting place.
Otherwise we force all users to do a lot of busywork which they might
find annoying.

Cheers

 - Martin
> --
> You received this message because you are subscribed to the Google Groups
> "scala-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to scala-user+...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Martin Odersky
EPFL

Jeffrey Shaw

unread,
Sep 13, 2015, 10:35:05 AM9/13/15
to scala-user, turingate...@gmail.com
After reading my post, I can see that it needs to be a bit more complicated.

search: "(\s+)\+(\s)+"

replace: "$1++$2"

Bruce Richardson

unread,
Sep 13, 2015, 6:08:47 PM9/13/15
to scala-user, turingate...@gmail.com
That will miss 1+1.  Your regex would need to match word boundaries to catch that.  And it would still fail with unary_+ (which may or may not be a good thing, depending on the circumstances).

Jeffrey Shaw

unread,
Sep 13, 2015, 9:24:32 PM9/13/15
to Bruce Richardson, scala-user, turingate...@gmail.com
And it'd miss string values on either side of the +. Never mind.

--
You received this message because you are subscribed to a topic in the Google Groups "scala-user" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scala-user/9h41cxPDvI8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to scala-user+...@googlegroups.com.

Jeffrey Shaw

unread,
Sep 13, 2015, 9:26:03 PM9/13/15
to scala-user, it.is...@gmail.com, turingate...@gmail.com
Ugh, I meant variables or values that are on either side of the +. Non-literal strings.
To unsubscribe from this group and all its topics, send an email to scala-user+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages