As a Rust programmer, I have the exact same lived experience of the language that the parent commenter does: that Rust can be relatively straightforward to write if you liberally clone things, but that the prevailing community norm strongly suggests that cloning is a code smell, or something you do in tooling-grade code.
The parent commenter was surprised that you suggesting liberal cloning was the way Rust code should be --- that, like, the median Rust crate should probably be written in the "clone liberally" register. You said that was the reason you wrote the Rust book aside. But I read that book and that aside and reached the opposite conclusion, and I think people who follow your link will mostly see why.
You haven't exactly cleared things up here, either. "For non-beginners, clone isn't a moral issue". Well, that's not what you just said upthread. I'm pressing you on this because it would be helpful to get an actual clear signal on this. Should most code be written with liberal clones, or should most beginner code be written with liberal clones? Like the previous commenter, I just want to understand what you're trying to say.
(A sibling comment here says the exact thing that I'm saying creates the mixed message here: that cloning is fine... in beginner code, but not in serious code.)
This is not, as we both know, a minor distinction in Rust; it is maybe the biggest stylistic distinction in actually writing Rust? Moreso maybe even than async?
> that, like, the median Rust crate should probably be written in the "clone liberally" register.
That is not what I understand myself to have said. The parent said that they "do not write much Rust code." That is very different than "the median Rust crate."
> Should most code be written with liberal clones,
I think this question is a category error. There is not enough context to give an opinion. And I think that means you cannot make a broad generalization about clone; some code should have a bunch of clones, and some code should not, even if they're the same code, because they operate in different kinds of contexts or sure, registers, to sort of stick to the vibes of the original post.
If I am presented the exact same code by two people, and one of them started writing Rust yesterday, and says "what do you think of my code?" I would not even give consideration to the number of clones when attempting to give them my opinion about their code. If someone came to me after writing Rust for ten years and said "hey I am struggling to improve performance in this code" and said "what do you think of my code?" and I saw a bunch of clones, I would say "have you profiled? I would suspect that maybe clones are causing your problem but I wouldn't do anything until I had a flame graph or equivalent." Even then that is not a moral question or answer, it is an engineering one.
> or should most beginner code be written with liberal clones?
Even this isn't exactly what I meant, but is closer. I mean what I said in my parent comment to you, beginners should not feel bad if their code uses clone, whatsoever. That does not then imply that non-beginners should feel bad, I said absolutely nothing in this thread about anything other than beginner code (until the paragraph above in this comment and the paragraph in the comment you're currently replying to).
It’s weird to me the degree to which you’re pressing an offhand comment into being some kind of Statement.
I’d expect anyone writing Rust regularly to know that the impact of Clone is context-dependent, and whether or not you should be fine with using it liberally is also context-dependent. Big object? Hot loop? Avoid cloning. Not worried about performance? Clone all you want if it makes the code easier and faster to write. You can always optimize later.
Sometimes it’s easy to avoid clones, and if you’re writing a lot of Rust it often feels like you might as well, just in case. But at least for my team, “you could get rid of this clone” is generally a take-it-or-leave-it kind of comment in code review.
There’s no easy way to express “it’s a trade-off between performance and ease of use that you’ll get better at with time” in a way that is instructive in any meaningful way, which is why I imagine it’s more useful to push people to err on the side of what’s going to be faster to get them to the amount of experience they need to engage meaningfully with the question within their own context.
Well, if I can mostly ignore fussy ownership and borrowing stuff and just clone everything, all the time, getting rid of clones exclusively in places that I profile and learn to be in the hot path, and the resulting code will be idiomatic Rust, that would be welcome news to me. That's where I'm coming from.
My impression from Klabnik's most recent comment is that this isn't the case. Which is fine! It lines up with my previous assumptions about Rust idiom.
I'm not quite sure where the disconnect is either, but yeah, "should I clone everywhere" or "is cloning everywhere idiomatic" is just one of those models that is useful, but like all models, is invariably wrong in some cases.
Just as one example, consider a function I wrote. It accepts a &str as a parameter. Internally, among other things, it clones that &str into a String. If you asked me whether that was "idiomatic" devoid of any other context, I would say, "probably not? Why not just ask for the String or a Into<String> instead?" But it's not a certainty. Just a likelihood.
But now let's add context. The context is that that function I mentioned is Regex::new. Does that change my answer? You bet your ass it does. Because cloning that pattern string has now turned into a definitively negligible cost. (By many orders of magnitude.) And there is upside to accepting a &str: it's non-generic, a little easier to understand and is unlikely to ever run afoul of type inference. Those aren't huge upsides, but there is actually no downside here because of the context.
As others have pointed out, there is no one-size-fits-all answer to this question. There are models though, and those models (e.g., "don't worry about cloning while you're learning Rust") are very likely to serve you quite well. That might not be every path that everyone learning Rust always takes. But it's a decent bet in my experience.
> My impression from Klabnik's most recent comment is that this isn't the case.
Okay last comment in this sub-thread because I have to get back to my job here, which hilariously is adding some boxing and possibly cloning in order to improve a codebase.
I feel like I'm going crazy. I feel like this:
> if I can mostly ignore fussy ownership and borrowing stuff and just clone everything, all the time, getting rid of clones exclusively in places that I profile and learn to be in the hot path, and the resulting code will be idiomatic Rust
is exactly what my last comment said. This whole chain, in my experience, is me saying "clone is not a moral issue" and you saying "why are you saying that people that use clone should feel bad." So I need to bow out. I wish I could figure out where this disconnect is, but it's clear that this thread is not achieving that.
Your comments and much of this thread have been helpful to my understanding. (Like the Rust book!--thank you!). I also appreciate your effort to be kind/respectful/understanding, elevating the conversation, where others might have responded with anger or disparagement. Thanks for the example.
The parent commenter was surprised that you suggesting liberal cloning was the way Rust code should be --- that, like, the median Rust crate should probably be written in the "clone liberally" register. You said that was the reason you wrote the Rust book aside. But I read that book and that aside and reached the opposite conclusion, and I think people who follow your link will mostly see why.
You haven't exactly cleared things up here, either. "For non-beginners, clone isn't a moral issue". Well, that's not what you just said upthread. I'm pressing you on this because it would be helpful to get an actual clear signal on this. Should most code be written with liberal clones, or should most beginner code be written with liberal clones? Like the previous commenter, I just want to understand what you're trying to say.
(A sibling comment here says the exact thing that I'm saying creates the mixed message here: that cloning is fine... in beginner code, but not in serious code.)
This is not, as we both know, a minor distinction in Rust; it is maybe the biggest stylistic distinction in actually writing Rust? Moreso maybe even than async?