Why is string concatenation done with * not +

3,156 views
Skip to first unread message

Samuel Colvin

unread,
Jul 2, 2014, 3:17:25 PM7/2/14
to julia...@googlegroups.com
There's no method +(s1::String, s2::String) instead string concatenation has to be done with

  a="hello "*"world

This is pretty unusual and unintuitive, so I'm guessing there a really good reason for it? 

Patrick O'Leary

unread,
Jul 2, 2014, 3:40:43 PM7/2/14
to julia...@googlegroups.com

There's a theoretical motivation, which I'm no good at explaining, but it does generalize nicely:

"hello, "^3 == "hello, hello, hello, "

You can search the list (and I think also Github issues) a bit for Stefan's deeper explanations on the topic.

Spencer Russell

unread,
Jul 2, 2014, 3:41:42 PM7/2/14
to julia...@googlegroups.com
It's a bit tricky to track down the relevant discussions, but this one seems like one of the most to-the-point:

https://groups.google.com/forum/#!msg/julia-dev/4K6S7tWnuEs/RF6x-f59IaoJ

peace,
s

Ivar Nesje

unread,
Jul 2, 2014, 3:45:19 PM7/2/14
to julia...@googlegroups.com
Not everybody is convinced there is a good reason. See some discussion about it in https://github.com/JuliaLang/julia/issues/1771

John Myles White

unread,
Jul 2, 2014, 3:48:26 PM7/2/14
to julia...@googlegroups.com
String concatenation is not commutative. Addition is generally used for commutative operations. So if you're a mathematician, using addition for string concatentation seems very wrong.

 -- John

Samuel Colvin

unread,
Jul 2, 2014, 4:16:44 PM7/2/14
to julia...@googlegroups.com
humm, I'm tempted to say multiplication is generally (if not always) commutative too.

Anyway, some very interesting discussions, surely the point is that there should be a concise explanation about string concatenation in the docs somewhere, something like:

"you can do "hello"*"world" which is the same as string("hello", "world"), the reason we don't use + is ..., for performance you should use IOBuffer for repeated string concatenation, example..."

Also a more instructive error on "hello"+"world" would make since.

John Myles White

unread,
Jul 2, 2014, 4:18:55 PM7/2/14
to julia...@googlegroups.com
Matrix multiplication is almost never commutative.

 -- John

Stefan Schwarz

unread,
Jul 3, 2014, 6:26:37 AM7/3/14
to julia...@googlegroups.com
@John. Never agreed more. Perfect reasoning. 

Tobias Knopp

unread,
Jul 3, 2014, 7:45:49 AM7/3/14
to julia...@googlegroups.com
I am absolutely ok that string concatenation is done with *
One just as to get used to it. The issue seems that some popular languages use + instead.

I kind of like Samuels suggestion to give better error messages but this would essentially mean to implement + and throw an error.
This would be not so nice because + would be listed as a valid method for strings what it actually is not. Not sure how to handle this.
Maybe one could have some error throwing methods that are only there at the REPL?

Francesco Bonazzi

unread,
Jul 3, 2014, 7:59:54 AM7/3/14
to julia...@googlegroups.com


On Wednesday, July 2, 2014 9:48:26 PM UTC+2, John Myles White wrote:
String concatenation is not commutative. Addition is generally used for commutative operations. So if you're a mathematician, using addition for string concatentation seems very wrong.

In Wolfram Mathematica there is a multiplication operator for scalars (i.e. * or space), commutative, and a multiplication operator for matrices (i.e. "."), non-commutative. In any case, Mathematica does not allow to define custom types, maybe that's the reason they decided to have distinct operators. In contrast, the commutativity of product arguments may be determined by their types in Julia.

Patrick O'Leary

unread,
Jul 3, 2014, 8:35:00 AM7/3/14
to julia...@googlegroups.com

Julia, following MATLAB, also has distinct operators: `*` and `.*`. The first implements matrix multiplication, and the second scalar/elementwise. Of course, when there is only one element--scalar arguments--these operations do the same thing.

Samuel Colvin

unread,
Jul 3, 2014, 9:11:43 AM7/3/14
to julia...@googlegroups.com
Fundamentally I don't think it matters which mathematical operator we use for an operation that's not strictly mathematical (or at least most users don't think of as mathematical), everyone is quite happy with "x = 4" not having it's rigorous meaning of "x == 4". As long as there's a compact and clear way of doing string concatenation I'm happy. 

If most people want * that's fine especially as there would need to be a very good reason to change it now.

The point is that we should make it as easy as possible for people to transition to Julia from other languages, and this is one potential stumbling block.

I agree with Tobias's suggestion of a REPL, IJulia only +(s1::String, s2::String) that throws an informative error.

For my part I've updated Julia By Example to give an example and a link to this discussion.

Eric Davies

unread,
Jul 3, 2014, 9:33:10 AM7/3/14
to julia...@googlegroups.com
I think the '+' is not as prevalent as you might think. 

MATLAB: ['foo' 'bar']
R: paste('foo', 'bar', sep="")
Python/C++/Ruby: "foo" + "bar"
Perl/PHP: "foo" . "bar"
C: strcat(bufcontainingfoo, "bar")
Mathematica: "foo" <> "bar"

People coming from MATLAB and R (probably a very large portion of those trying Julia) are already used to something else. There may be a lot of Python programmers as well, but Julia isn't trying to target Python users specifically.

I think having a +(String, String) defined with a helpful error would be a good idea, and I don't think it needs to be confined to the REPL (unless something in the language depends on seeing method missing errors).

Ivar Nesje

unread,
Jul 3, 2014, 9:42:09 AM7/3/14
to julia...@googlegroups.com
I would strongly argue against

+(a::String, b::String) == Error("Use * for string concatenation")

We have plenty of cases where we want to give a more helpful `MethodError`. We should really create a simple system where you can get those hints printed in the REPL, without defining more methods.

The display of MethodError is defined in https://github.com/JuliaLang/julia/blob/0df386db18dd186c7b0bffc74149fc6b0e51c67d/base/replutil.jl#L110 and it would be easy to have a lookup table at the end of that function to see if one of the "banned" methods (with usefull, more concistent alternaltives) were called.

Ivar

Tobias Knopp

unread,
Jul 3, 2014, 10:06:42 AM7/3/14
to julia...@googlegroups.com
Ivar, I absolutely agree with you. This should be handled in a larger scope. Do we have an issue for this yet?

Ivar Nesje

unread,
Jul 3, 2014, 10:10:08 AM7/3/14
to julia...@googlegroups.com
I don't think so. I'll open one.

Tobias Knopp

unread,
Jul 3, 2014, 10:17:22 AM7/3/14
to julia...@googlegroups.com
Great, thanks!

Samuel Colvin

unread,
Jul 3, 2014, 10:32:00 AM7/3/14
to julia...@googlegroups.com
Larger scope makes a lot of sense.

Please give a link to the issue here once it's created.

Ivar Nesje

unread,
Jul 3, 2014, 10:33:49 AM7/3/14
to julia...@googlegroups.com

Stefan Karpinski

unread,
Jul 3, 2014, 10:46:12 AM7/3/14
to Julia Users
On Thu, Jul 3, 2014 at 9:42 AM, Ivar Nesje <iva...@gmail.com> wrote:
We should really create a simple system where you can get those hints printed in the REPL, without defining more methods.

Yes, I think we should really pursue this avenue.

For what it's worth – and perhaps something since I'm the original perpetrator of the str*str concatenation syntax – I've come to regret this operator choice. My reasoning at this point is that we want our operators to have fairly "pure" meanings. I chose str*str because concatenation can be viewed as a kind of multiplication in the ring of string patterns (alternation in the regex sense is the addition operation, the empty string is the unit and the non-matching pattern is the zero). However, many operations can be viewed as a form of multiplication. In the max-plus algebra, for example, addition is the multiplication operator. So, at this point I think we should stick to very pure classical meanings for operators in Base – the Base.* function should be just addition of numbers in the classical sense, not the broader sense of addition in any conceivable ring.

yi lu

unread,
Jul 3, 2014, 10:52:39 AM7/3/14
to julia...@googlegroups.com
I will vote for "+", although I learn mathematics. Maybe that is why I am not a mathematician.

Yi

Stefan Karpinski

unread,
Jul 3, 2014, 10:54:08 AM7/3/14
to Julia Users
That's even worse.

yi lu

unread,
Jul 3, 2014, 10:57:54 AM7/3/14
to julia...@googlegroups.com
@John I know that "*" means no commutative, but I see no reason "+" has a meaning of commutative.

John Myles White

unread,
Jul 3, 2014, 10:59:50 AM7/3/14
to julia...@googlegroups.com
This is just the standard convention in mathematics. See just about any textbook on abstract algebra for a discussion of the reasons.

I think it's safe to say that `+` will never be string concatenation, so it's better to focus energy on other proposals.

 -- John

yi lu

unread,
Jul 3, 2014, 11:09:08 AM7/3/14
to julia...@googlegroups.com
I know abstract algebra. When talking about string concatenation, a monoid is enough. It is true that in a ring, "+" is a commutative operator, and "*" no commutative required, however, a ring is far beyond what needed to do a string concatenation job.

Stefan Karpinski

unread,
Jul 3, 2014, 11:12:38 AM7/3/14
to Julia Users
Please read my email about why * is not good for string concatenation. Then reread the same email replacing * with +.

John Myles White

unread,
Jul 3, 2014, 11:14:00 AM7/3/14
to julia...@googlegroups.com
That is true, but the convention exists nonetheless. Consider, for example, this branch of the combinatorics literature: http://en.wikipedia.org/wiki/Square-free_word

 -- John

yi lu

unread,
Jul 3, 2014, 11:34:22 AM7/3/14
to julia...@googlegroups.com
When you talk about convention, you regard julia language as a programming language like MATLAB or a more general purpose language? Again, it is all about string concatenation, not operations on a ring.

yi lu

unread,
Jul 3, 2014, 11:36:38 AM7/3/14
to julia...@googlegroups.com
However, to be honest, I don't need much of the string functions. I only need functions that operate vectors or matrices.

John Myles White

unread,
Jul 3, 2014, 11:38:12 AM7/3/14
to julia...@googlegroups.com
Because Julia uses multiple dispatch, an effort is being made to ensure that all functions always mean the same thing. So the mathematical case affects the non-mathematical case.

I'm checking out of this conversation now so that I can get back to my actual job. I'm confident Stefan will make a good decision about this in due time.

 -- John

Gregg Reynolds

unread,
Jul 3, 2014, 11:49:26 AM7/3/14
to julia...@googlegroups.com
Hi!

I would add "minimal" and "intuitive".  I agree '*' is an unfortunate choice for a string concat op, but I don't see a problem with '+' - mathematics routinely overloads symbols, and I don't see any strictly mathematical reason to privilege commutativity as an essential component of the meaning of '+'.  Commutativity is an add-on that comes after the more primitive sense of accumulation, which is what concatenation is.  You can't build a brick wall from the top down.  I think its a pretty safe bet that nobody would ever be tempted to think "ab" + "cd" = "cd" + "ab", ditto for "++".  On the other hand, if you want to minimize overloading, an alternative notation (my fav), used by Z and ML, among other languages, is '^'; since that's already taken, maybe '^^'.

In any case, str * str isn't all that tragic; think of it as a beauty mark, a flaw that makes the whole face more beautify. ;)

-Gregg Reynolds

Patrick O'Leary

unread,
Jul 3, 2014, 12:09:41 PM7/3/14
to julia...@googlegroups.com
On Thursday, July 3, 2014 9:46:12 AM UTC-5, Stefan Karpinski wrote:
For what it's worth – and perhaps something since I'm the original perpetrator of the str*str concatenation syntax – I've come to regret this operator choice.

Since everyone else likes to disagree with this operator choice, I'll just mention that after some initial confusion I've come around. It's not something I use all that often, but I do find the generalization to string exponentiation -> repetition is pretty beautiful.

What fascinates me about the whole thing is that people get really attached to string concatenation operators...

yi lu

unread,
Jul 3, 2014, 12:11:49 PM7/3/14
to julia...@googlegroups.com
What a beautiful comment. :)

Stefan Karpinski

unread,
Jul 3, 2014, 12:12:47 PM7/3/14
to Julia Users
On Thu, Jul 3, 2014 at 12:09 PM, Patrick O'Leary <patrick...@gmail.com> wrote:
I do find the generalization to string exponentiation -> repetition is pretty beautiful.

This is my favorite part about the * choice. From str+str it's not at all obvious whether 2str or str*2 is the right choice for string repetition. I also agree that's fascinating how attached people get to string concatenation operators. Don't get Jeff started on string interpolation, which is essentially a fancy string concatenation syntax.

Pierre-Yves Gérardy

unread,
Jul 3, 2014, 6:41:28 PM7/3/14
to julia...@googlegroups.com
FWIW, Lua uses  ..  for concatenation.  The operator is right associative... I don't know why.

—Pierre-Yves

Laszlo Hars

unread,
Jul 3, 2014, 10:31:42 PM7/3/14
to julia...@googlegroups.com
Of course, 2str, 2*str and str*2 could be equivalent, as they are for other data types. For me two (copies of) str is just more natural than str1 times str2. Similarly, "add" str2 to str1 for concatenation follows the natural language better. Also, you could define str1-str2 as deleting str2 from (the beginning/end of) str1, if it was there. (even though str2/str1 works, too). You can find in algebra ample examples for both multiplicative and additive notations for structures, but either way the notation of string concatenation is the least of our difficulties when learning Julia.

Gunnar Farnebäck

unread,
Jul 5, 2014, 1:40:27 PM7/5/14
to julia...@googlegroups.com
Here's an example of a language that does a bit more with string operations.

% pike
Pike v7.8 release 700 running Hilfe v3.5 (Incremental Pike Frontend)
> "ab" + "c";
(1) Result: "abc"
> "abc" * 2;
(2) Result: "abcabc"
> "abcabc" - "ca";
(3) Result: "abbc"
> "abcabc" / "b";
(4) Result: ({ /* 3 elements */
                "a",
                "ca",
                "c"
            })
> ({"a", "b", "c"}) * "x";
(5) Result: "axbxc"

Laszlo Hars

unread,
Jul 5, 2014, 1:55:28 PM7/5/14
to julia...@googlegroups.com
Pike's string operators are much more intuitive, thus easy to remember. If ever there will be a chance to change Julia's standard string operators, I would vote for taking over Pike's. (Of course, we can define these for ourselves, but the resulting code will not be portable.)

Kevin Squire

unread,
Jul 5, 2014, 11:21:15 PM7/5/14
to julia...@googlegroups.com
One good way to push this idea forward would be to create a package which defines these operators, and then encourage people to try it. 

Cheers,
   Kevin
Reply all
Reply to author
Forward
0 new messages