# The strangeness (or not) of \* as string concatenation

**URL:** <https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943>\
**Category:** General Usage\
**Created:** [August 26, 2025, 2:14pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943 "2025-08-26T14:14:07Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)\
**Post date:** [August 26, 2025, 2:14pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/1 "2025-08-26T14:14:07Z")

</div>

> [@Is it possible to define '+' operator for string as '\*' do for them?](https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/9):
>
> but ‘\*’ looks strange for me…

It looks strange to me, too, and I think it was a particularly poor choice in the design of the Julia language. And, quite frankly, I consider the [“explanation”](https://docs.julialang.org/en/v1/manual/strings/#man-concatenation) borderline offensive… but the important point is

> [@Is it possible to define '+' operator for string as '\*' do for them?](https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/4):
>
> when you learn a new language, you should try to learn the idiomatic “spelling” of things in that language

That is, don’t try to bend the language to existing idioms in languages you may already be familiar with. Just learn the syntax and the idioms native to Julia, and take them as a given.

And, not really directly related but even more important (hence my original curt response): everyone should be maximally allergic to defining methods for functions they don’t own on a set of arguments they don’t fully own (aka “type piracy”). Never, ever do it unless you _really_ understand the implications of what you’re doing. Without that, it can easy lead to catastrophic correctness bugs, and it continues to be the source of major latency issues within the language by causing invalidations.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 26, 2025, 2:30pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/2 "2025-08-26T14:30:44Z")

</div>

Honestly I didn’t get how troublesome `+` would be for strings in Julia until recently — when I started really hammering on reductions. It’s not all that unusual to consider concatenating a bunch of strings with a reduction. But if we used `+` then folks could (and I’d wager would) end up writing `sum(strs)` (or more straightforwardly `reduce(+, strs)`) to do this. And that _might_ jumble up the orderings!

This is in contrast to using `prod` or `reduce(*, strs)`, which is guaranteed to preserve the orderings. I still wouldn’t encourage doing this, but at least _it won’t do the wrong thing!_

---

<div class="post-metadata">

**Author:** ![braamvandyk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/braamvandyk/32/5086_2.png) [@braamvandyk](https://discourse.julialang.org/u/braamvandyk)\
**Post date:** [August 26, 2025, 2:40pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/3 "2025-08-26T14:40:16Z")

</div>

Funny thing, considering the number of Excel users, that no-one ever asks for ‘&’ for string concatenation in Julia…

---

<div class="post-metadata">

**Author:** ![obsidianjulua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/obsidianjulua/32/221495_2.png) [@obsidianjulua](https://discourse.julialang.org/u/obsidianjulua)\
**Post date:** [August 26, 2025, 2:52pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/4 "2025-08-26T14:52:29Z")

</div>

Thats a replicode thing

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 26, 2025, 5:11pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/5 "2025-08-26T17:11:11Z")

</div>

> [@mbauman](#):
>
> But if we used `+` then folks could (and I’d wager would) end up writing `sum(strs)` (or more straightforwardly `reduce(+, strs)`) to do this. And that _might_ jumble up the orderings!

Why? `reduce` assumes that the operator is associative, but not commutative — the implementation can change the associativity, but not the ordering. And `*` is associative.

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [August 26, 2025, 5:30pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/6 "2025-08-26T17:30:50Z")

</div>

> [@goerz](#):
>
> And, quite frankly, I consider the [“explanation”](https://docs.julialang.org/en/v1/manual/strings/#man-concatenation) borderline offensive…

Why, what am I missing here? The only thing I could object to is that in my opinion `*` carries no connotation of (non)commutativity at all, i.e. it could go either way (e.g. matrix multiplication, convolution).

---

<div class="post-metadata">

**Author:** ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)\
**Post date:** [August 26, 2025, 5:41pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/7 "2025-08-26T17:41:08Z")

</div>

> [@mbauman](#):
>
> Honestly I didn’t get how troublesome `+` would be for strings in Julia until recently

I don’t follow…

> [@mbauman](#):
>
> writing `sum(strs)` (or more straightforwardly `reduce(+, strs)` […] _might_ jumble up the orderings!

It better not! There is nothing in the Julia language that would enforce some kind of commutativity of `+`. I can easily imagine a type for which a direct sum is implemented via `+` in lieu of the more correct `⨁` – and direct sums are not commutative in the sense most people would expect (only up to isomorphisms: For two matrices A and B, `A ⨁ B` is a different matrix than `B ⨁ A`, even if they’re isomorphic, with a change of basis). And there are certainly many _colloquial_ uses of “plus” that are inherently non-commutative (including string concatenation: “put your first name plus last name in this field”)

The docstrings of neither `sum` nor `prod` say anything about this _explicitly_, but `reduce` guarantees preserving the order (assuming the underlying collection is ordered). It only makes assumptions about associativity. I would expect this behavior to translate back to `sum` and `prod`, as I’m sure it does.

I don’t think there would be anything wrong if we had chosen `+` for string concatenation, or if people were using `sum(strings)` to concatenate strings. At the end of the day it should boil down to “Julia uses `*` for string concatenation”, and leave it at that. I wish Julia wouldn’t be the _only_ language using `*`, but had chosen any of the “prior art” of `+`, `.`, `..`, `~`, `&`, `\\`. But okay. Just that ridiculous “abstract algebra” justification should be stricken from the record. Strings are not a field of vectors with a bilinear product! None of that mathematical structure applies even remotely in this situation. And of course, _most_ fields _are_ commutative, so 99.9% of all `*` symbols are just as commutative as `+` symbols (despite, as a quantum physicist, non-commutative algebras being my bread and butter). I can guarantee that nobody ever would have been confused by a non-commutive `+` for string concatenation. Alas. /end rant

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [August 26, 2025, 5:47pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/8 "2025-08-26T17:47:18Z")

</div>

> [@stevengj](#):
>
> Why? `reduce` assumes that the operator is associative, but not commutative — the implementation can change the associativity, but not the ordering. And `*` is associative.

For better or worse, there are a [number of implementations](https://github.com/search?q=CommutativeOps+language%3Ajulia&type=code) that take do take advantage of the commutativity of `+`, even with arbitrary element types! And while the compiler transformation underpinning `@simd` is called [`reassoc`](https://llvm.org/docs/LangRef.html#rewrite-based-flags), it _actually_ does a reordering! Now, yes, Julia won’t do this `@simd`-based reordering for non-simdy datatypes, and `+` truly is commutative for the simdy datatypes. I don’t _think_ it’s possible, but I’m still not fully convinced it’s impossible to divine up a non-commutative struct for which `@simd` would do the wrong thing. But even without SIMD instructions, doing a SIMD-like reordering can be significantly advantageous for pipelining processors.

---

<div class="post-metadata">

**Author:** ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)\
**Post date:** [August 26, 2025, 5:57pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/9 "2025-08-26T17:57:15Z")

</div>

> [@mbauman](#):
>
> For better or worse, there are a [number of implementations](https://github.com/search?q=CommutativeOps+language%3Ajulia&type=code) that take do take advantage of the commutativity of `+`, even with arbitrary element types!

Well, if true, that’s a major correctness bug waiting to blow up in our collective faces. You can’t just assume that every `+` everywhere is commutative for non-numbers.

> Julia won’t do this `@simd` -based reordering for non-simdy datatypes

That’s fine then… if you do it in a context where you know the operands of `+` and can guarantee that `+` is commutative in this context, optimize away.

But just blindly assuming the operater `+` as a member of some `CommutativeOps` is a code smell, at the very least, and we shouldn’t be nonchalant about it.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [August 26, 2025, 6:08pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/10 "2025-08-26T18:08:59Z")

</div>

Just a simple warning to not do type piracy. By example. John von Neumann’s definition of natural number is very simple. 0 is the empty set, a positive integer is the set of smaller natural numbers.

I once illustrated this live as follows ( **This messes up your julia session!** )

```julia-auto
Base.iterate(i::Int, state::Int=0) = (state ≥ i) ? nothing : (state, state+1)
Base.length(i::Int) = i
Base.IteratorSize(::Type{Int}) = Base.HasLength()
Base.eltype(::Type{Int}) = Int

julia> for i in 4
           println(i)
       end
0
1
2
3

julia> collect(5)
5-element Vector{Int64}:
 0
 1
 2
 3
 4

```

Neat.

Then, I forgot to restart julia. Now, my new definition is at odds with the julia default, where `collect(5)[] == 5`, and `for i in 4 ... end` is a single iteration with `i == 4`. Some parts of julia, and some packages, depend on this behaviour. And my change is in `Base`, so it’s global. Chaos followed, until I remembered what I had done.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [August 26, 2025, 6:35pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/11 "2025-08-26T18:35:33Z")

</div>

> [@goerz](#):
>
> None of that mathematical structure applies even remotely in this situation

this also bugs me occasionally. another example is the [docs for `/`](https://docs.julialang.org/en/v1/base/math/#Base.:/)

> Right division operator: multiplication of `x` by the inverse of `y` on the right.

seemingly motivated by traditional algebraic definitions. but this does not correctly describe the behavior of floating point arithmetic

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [August 26, 2025, 8:33pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/12 "2025-08-26T20:33:56Z")

</div>

> [@goerz](#):
>
> Strings are not a field of vectors with a bilinear product! None of that mathematical structure applies even remotely in this situation.

I don’t think vectors or fields are mentioned in the explanation, but monoids are.

For all `s,t,u :: String`, we have

- `"" * s == s`
- `s * "" == s`
- `s * (t * u) == (s * t) * u`

which seems like a monoid.

> [@Is it possible to define '+' operator for string as '\*' do for them?](https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/21):
>
> For better or worse, there are a [number of implementations](https://github.com/search?q=CommutativeOps+language%3Ajulia&type=code) that take do take advantage of the commutativity of `+`, even with arbitrary element types!

When library authors make an assumption that library users are unaware of, we’re at risk of correctness problems. Is there any chance we could put “implementers should be commutative” in the `Base.+` docstring? Or “implementers may or may not be commutative”? Either way I think it would help reduce the risk of miscommunication.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [August 26, 2025, 10:15pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/13 "2025-08-26T22:15:36Z")

</div>

> [@jar1](#):
>
> which seems like a monoid.

sure, but `+` could have been the symbol for that just fine as monoids only have one operation

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [August 26, 2025, 11:13pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/14 "2025-08-26T23:13:12Z")

</div>

> [@adienes](#):
>
> sure, but `+` could have been the symbol for that just fine as monoids only have one operation

That’s true. However, if we did that then we couldn’t say “`+` implementers should be commutative”, which is a nice property for `+` to have because `+` is also used commutatively for numbers and arrays. Using `*` for `String`s we can say “`*` implementers should be (approximately) associative”. Giving contracts to generic functions is a good idea, imo.

Of course, those restrictions are not currently in the docstrings for those operators, but I’d like them to be.

So I think `*` is fine (albeit unusual), but I’d be also happy with `++` or [`append(...)`](https://github.com/JuliaLang/julia/issues/53040) which could be implemented by any sequence type, such as `Vector`s. I just want generic `function`s to have strong generic contracts that both library authors and users can count on (and any violations are done intentionally not accidentally).

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [August 27, 2025, 12:32am UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/15 "2025-08-27T00:32:11Z")

</div>

> [@goerz](#):
>
> You can’t just assume that every `+` everywhere is commutative for non-numbers.

For example, addition of [ordinal numbers](https://en.wikipedia.org/wiki/Ordinal_arithmetic#Properties) is not commutative, and digging deeper can unearth more niche non-commutative generalizations of the addition of natural or real numbers. I’d agree that commutativity isn’t a property of numerical types or operations in isolation like a supertype or interface, it often must take both into account like a multiply-dispatched Holy trait. That could also help optimize `*` as well; non-commutative multiplication of matrices and quaternions (or concatenation of strings) don’t need to prevent optimizations for commutative multiplication of other types.

Pretty sure implementing `+` commutativity is unrelated to aesthetically replacing `*` for concatenation, I’d say this should be split to a separate thread.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 27, 2025, 8:31am UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/16 "2025-08-27T08:31:15Z")

</div>

> [@goerz](#):
>
> I consider the [“explanation”](https://docs.julialang.org/en/v1/manual/strings/#man-concatenation) borderline offensive…

I curious, which part of the explanation are you referring to?

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [August 27, 2025, 11:49am UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/17 "2025-08-27T11:49:56Z")

</div>

I can only speak for myself, but the blurb about free monoids just reeks of This Decision Is Correct Because I Am Smarter Than You

like yes, I do know what a monoid is, and yes I see that `String` endowed with `*` is one, but it just feels pretty pretentious to be appealing to a definition from mathematical objects that are super irrelevant. I would have much preferred that just say “`*` is used for string concatenation because `+` often implies commutativity” and leave it at that.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 27, 2025, 12:09pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/18 "2025-08-27T12:09:51Z")

</div>

> [@adienes](#):
>
> I would have much preferred that just say “`*` is used for string concatenation because `+` often implies commutativity” and leave it at that.

I can sympathize with that, especially since this is the _only_ place the term monoid is used in the manual. Nevertheless, I don’t think that the intention was to offend anyone.

Generally, I am not easily offended, especially by explanations, so I don’t mind this being in the manual, but perhaps a PR removing this and rewording would make sense.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [August 27, 2025, 12:10pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/19 "2025-08-27T12:10:34Z")

</div>

Should we mark some answer as answering this question? The top one saying “yes”, or the one above with “no”…? Or even mine here?

The discussion that followed is interesting (to me), I hope we’re not scaring new users away in “New to Julia” group. I believe the answer is yes, you CAN, define `+`, and using that `+` alone in your code will always be ok, but seemingly not with `sum` (who would use for `string`s?). But it doesn’t mean you really should do this for your own code, let alone for packages, i.e. help others do this.

> [@Is it possible to define '+' operator for string as '\*' do for them?](https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/27):
>
> So I think `*` is fine (albeit unusual), but I’d be also happy with `++` or [`append(...)`](https://github.com/JuliaLang/julia/issues/53040) which could be implemented by any sequence type, such as `Vector`s.

> [@Is it possible to define '+' operator for string as '\*' do for them?](https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/12):
>
> Take also a look [at this thread](https://discourse.julialang.org/t/introduce-as-the-concatenation-operator/37418/61) and the tiny Julia package [PlusPlus.jl](https://juliaregistries.github.io/General/packages/redirect_to_repo/PlusPlus) with just three lines of code.

This is interesting, but even more interesting to me would be an operator that seemingly concatenates strings, but doesn’t actually, returns a concat type of prefix and suffix, only lazily doing an actually concatenation, maybe never in practice. If you concat again, you might naively get a tree of that type, but then I think we went to far, and we could only ever have two parts, not doing the concat until we really need it e.g. for a regex, or to call C code that expects the string linear in memory.

> [@mbauman](#):
>
> Honestly I didn’t get how troublesome `+` would be for strings in Julia until recently … But if we used `+` then folks could (and I’d wager would) end up writing `sum(strs)` (or more straightforwardly `reduce(+, strs)`) to do this. And that _might_ jumble up the orderings!

I’m still not sure from the discussion, if sum would be a problem… in reality, even is used…

---

<div class="post-metadata">

**Author:** ![goerz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerz/32/3269_2.png) [@goerz](https://discourse.julialang.org/u/goerz)\
**Post date:** [August 27, 2025, 1:02pm UTC](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943/20 "2025-08-27T13:02:44Z")

</div>

> [@Is it possible to define '+' operator for string as '\*' do for them?](https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/29):
>
> > [@goerz](#):
> >
> > I consider the [“explanation”](https://docs.julialang.org/en/v1/manual/strings/#man-concatenation) borderline offensive…
> 
> I curious, which part of the explanation are you referring to?

Don’t take the comment _too_ seriously, but

[https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/30?u=goerz](https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/30)

captures it quite well. “Offended” was a bit of rhetorical hyperbole, more like “eye-roll”, as in, with absolute respect for the Julia inventors, “people had their heads way too far up their mathematical asses when this was decided” 😉 I think we should be wary of that kind of mathematically pedantic mindset. While it may have _some_ charm, that wears off pretty quickly, and then can be rather off-putting, especially to new users. A more recent and more egregious example (not to veer of too far off-topic in this thread again) was the opposition to using `/` to join paths, cf.

> [@Is it possible to define '+' operator for string as '\*' do for them?](https://discourse.julialang.org/t/is-it-possible-to-define-operator-for-string-as-do-for-them/131835/24):
>
> another example is the [docs for `/`](https://docs.julialang.org/en/v1/base/math/#Base.:/)
> 
> > Right division operator: multiplication of `x` by the inverse of `y` on the right.
> 
> seemingly motivated by traditional algebraic definitions. but this does not correctly describe the behavior of floating point arithmetic

This is not to say I’m opposed to rigorous and precise interfaces. Quite the opposite. But operators can have different meanings in different contexts. Nobody is going to be confused with `+` or `/` having a different meaning for strings or paths than for numbers.

[Next page](https://discourse.julialang.org/t/the-strangeness-or-not-of-as-string-concatenation/131943.md?page=2)
