Implement Add for String + String

@ehiggs I wish the * -> RetType search pattern was better documented, it's one "hidden" gem of the rust docs: example for your case (slice::join and slice::concat appear among the first 10 results).

Regarding overloading Add, I agree with @DanielKeep on this one: since adding chars is not very intuitive, adding sequences of chars is not very ambiguous, thus people can see the appeal of it. But quid of Vec<char>? And Vec<u8>? And Vec<T>? I agree it's a slippery slope and only a matter of time before those are requested too. But when T : Add, the "sum" of two sequences of T is now ambiguous.

The solution? Do have a fn (String, String) -> String operation (this would solve OP's use case, for instance), but do not call it Add::add. If you want sugar, other sigils can be used (someone mentioned ~, Ocaml uses @ for list concatenation, but my favorite sugar would be abstracting .. with a trait that remains compatible with the current fn (Idx, Idx) -> Range<Idx> behavior, but that would also allow using it for more general concatenations). But please do not use addition notation.

7 Likes

One obvious analogy is matrix multiply, where the Mul trait conceptually applies to both pairwise element-by-element multiplication of two identically-sized matrices and to the cross-product of the two matrices. Both operators return a third identically-sized matrix. However, overloading Mul for both purposes so that the convenient sigil * could be used would lead to ambiguous code.

1 Like

That has already been shown to not be backwards compatible.

I would love to have + for String + String. I don't want new sigils, though. Rust has enough. If you wanted to concatenate multiple Strings (not just &str, which can already be done), it might be doable with a new trait (e.g. TupleConcatExt) that has a concat() method for tuples where each element of the tuple satisfies Borrow<str> or something like that (I haven't thought through this, it might be a terrible idea).

But multi-string concatenation is only tangentially related to + for String + String. I hope we can get String + String without being paralyzed by fear of people writing suboptimal String + String + String code.

2 Likes

Addition is commutative, but concatenation is not. They’re also really not the same thing imho.

3 Likes

At least two others have noted in this thread that the ship for + for concatenation has long since sailed. If anyone wants to deprecate it or introduce a new concatenation operator, I would encourage them to draft an RFC.

3 Likes

Some types of mathematical addition are not commutative, just as (a + b) * c is not truly distributive for finite-precision floating point numbers. There is a long history in mathematics of overloading operator sigils in ways that do not maintain the commutative, associative, and distributive properties of the infinite ring of integers and field of real numbers.

17 Likes

Just pointing out that we might want to change the current suggestion then, so instead of telling people .to_owned() we tell them to use [].join(""). Is that something we should be looking at?

1 Like

It's a good question. It's probably worth it for bigger chains of +, but I don't know for just two things.

(Also, I forgot that there's [a, b].concat(), which is clearly better than [a, b].join("").)

2 Likes

It seems to me that the generalization to N items would best be handled by variadics. Any idea where they are on Rust’s development schedule?

1 Like

Not this year; maybe by rust 2021.

That said, this is homogeneous generics, so I think the “just pass an array” version is fine.

1 Like

I, too, think that using + for concatenation is a mistake that should not be compounded on. As others have pointed out, a concatenation-specific operator would be useful for other containers as well, esp. with extended generics. For example:

[1, 2, 3]  + [4, 5, 6] -> [5, 7, 9]
[1, 2, 3] ++ [4, 5, 6] -> [1, 2, 3, 4, 5, 6]

Or with tuples:

(1, 2.0, 3)  + (4, 5.0, 6) -> (5, 7.0, 9)  // error if not pairwise addable
(1, 2.0, 3) ++ (4, 5.0, 6) -> (1, 2.0, 3, 4, 5.0, 6)
4 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.