If you want to get the semantics of other languages, just clone the left-hand side with ".clone()".
Isn't that true for every language?
No offense intended, but this strongly reminds me of the "Sufficiently Smart Compiler" [1]
The Java community had more than enough time to implement that, especially compared to a young language like Rust, so there's probably a reason they don't have it yet.
javac compiles chained string concatenation to a sequence of StringBuilder calls, and HotSpot knows how to specifically optimize those:
https://groups.google.com/forum/m/#!topic/jvm-languages/KtVB...
That said, I'm sure there are common cases it doesn't catch.
Closest real world example to a sufficiently smart compiler is GHC, and that can be plenty dumb at times.
Here, SQL can also be viewed as a lazy evaulated programming language, due to its declarative nature and the fact that the execution order is not defined in the code, but instead an (hopefully optimal) execution order is determined by the query planner.
Which, string handling being specifically optimised by the compiler, is exactly what was being discussed upthread?
https://www.reddit.com/r/rust/comments/67rjii/question_about...
The basic problem is that str slices exist in the "core" library, which can be used on targets without an allocator (for example bare-metal embedded systems), while the owned String type exists only in the "std" library, which requires an allocator. Rust has rules that prevent one library from stomping on another library's types in certain ways that could conflict with future API additions, and those apply to the standard libraries here. (One solution would be to allow the author of libraries A and B to declare that A is allowed to treat types from B as though they were its own.)
The part beginners tend to get wrong is trying to add a &str to a &str, which just doesn't have a + implementation to begin with, so they get lost.
Turns out my assumption (like C++, make expensive things more verbose) isn't the complete picture. The big blocker is a technical issue preventing `"" + ""`
See https://github.com/rust-lang/rust/issues/39018#issuecomment-...
In a systems language, allocations matter. As such, people are generally really against hidden allocations in Rust, moreso than in other languages. This totally could have been done, but by requiring a String on the left, you are already in "this is heap allocated" land, and that is much more palpatable for Rust's audience.
=palpable + palatable. Pedantry aside though, I like the word. Maybe it describes something can be palpably palatable.
We could make the addition operator implicitly allocate here. It's a bit of a philosophical question if implicit allocations like that are desirable in rust. I lean towards being okay with the implicit allocation.
In other words, it would violate the conventions, but not the rules.
(Okay so there's a _really_ obscure rule here that sill prevents this but it only matters because it's the standard library. It's not actually the signature)
fn main () {
let hello = "Hello".to_owned();
let world = "world";
let hello_world = hello + world;
print!("{}, {}", hello_world, hello)
}
4 | let hello_world = hello + world;
| ----- value moved here
5 | print!("{}, {}", hello_world, hello)
| ^^^^^ value used here after move
= note: move occurs because `hello` has type `std::string::String`, which does not implement the `Copy` trait
The docs are also pretty awesome as well [0]. They also point out most of this and list out all the types which implement the copy trait.> Copies happen implicitly, for example as part of an assignment y = x. The behavior of Copy is not overloadable; it is always a simple bit-wise copy.
> Cloning is an explicit action, x.clone(). The implementation of Clone can provide any type-specific behavior necessary to duplicate values safely. For example, the implementation of Clone for String needs to copy the pointed-to string buffer in the heap. A simple bitwise copy of String values would merely copy the pointer, leading to a double free down the line. For this reason, String is Clone but not Copy.
> Clone is a supertrait of Copy, so everything which is Copy must also implement Clone. If a type is Copy then its Clone implementation need only return *self (see the example above).
I haven't really used Rust at all, but the more I look at it the more I want too. I probably will not be given the opportunity anytime soon though. Such is life in the world of frontend development.
a man can dream.
Pretty much the same, string literals are of type &'static str, which is a string slice with a static lifetime. Since literals are not `mut`, you cannot mutate them.
Back when I did more embedded stuff we cared since it could increase your runtime memory by a non-trival amount depending on what the platform did.
The auto copy to the heap behavior is controversial, desired by many for ergonomic reasons, disliked by others for implicit heap allocation. We'll see if it gets added in the future or not!
Thanks for the details, it's appreciated.
I don't really know Rust, but isn't that weird? In most languages I know, I would expect for example Vector3(1, 2, 3) + Vector3(2, 3, 4) to return a brand new Vector3(3, 5, 7), with Vector3(1, 2, 3) unmodified? Unless I do vector1 += Vector3(2, 3,4), at which point I expect vector1 to be modified without creating a new vector?
Why doesn't rust create a new String and concatenates using this new owned String? I guess that's why beginners get it wrong - I would