r/learnrust • u/LetsGoPepele • 4d ago
More concise way to write `self.some_vec.iter().copied()` ?
In a &self method, when I have a Vec of Copyable data and I want to iterate over owned values, either I iterate over references and dereference inside the loop body (I don't really like this style), or I have to do this iter().copied() boilerplate. Not a big deal, but is there some syntax that I'm missing ?
Edit: toy code
struct Foo {
some_vec: Vec<i32>,
}
impl Foo {
fn iterate(&self) {
for v in self.some_vec.iter().copied() {
do_some_stuff(v);
}
}
}
fn do_some_stuff(v: i32) {
....
}
7
u/RazorBest 4d ago
I'm curious: is there a real life use case for wanting to copy a value, and cloneing it would have a different effect?
I know it's possible to have something like: ```
[derive(Copy)]
struct A(i64);
impl Clone for A { fn clone(&self) -> Self { A(self.0 +1) } } ```
But I wouldn't imagine a case where someone would ever do such a thing.
8
u/Pleasant-Couple6236 4d ago
Not really, I think the rationale for having two distinct traits for this is that
Copyshould only be (can only be?) used for very fast copies that only touches the stack, copying individual ints, pointers etc, while usingClonesignals it might be performing a deep copy, allocating potentially large new data structures on the heap.3
u/garagedragon 3d ago edited 3d ago
Copy means specifically that creating a copy can be done by directly copying bits with no additional logic, which means as a side effect the original value can still be reused and isn't consumed by moves. It is usually, but not guaranteed to be fast, because very large structures can still be Copy if they're plain data, like say, [u8; 4096]. IIRC you must derive Copy, you can't manually implement it, so all the fields of a copy type are also necessarily Copy. (It is not just a marker trait on top of Clone in the way Eq is on PartialEq) Copying is still deep, if you can do it at all, since it'll also copy all fields by value. It's also not intrinsically tied to stack/heap, you can copy values to and from the interior of a Box even though the Box handle itself is not Copy because it needs to ensure it's pointer is unique.
Clone is conceptually the same operation, but it's allowed to run arbitrary code. There's no actual requirement that Clone do the same thing as Copy if the latter is implemented, but IMO there's no sensible reason you'd have a Copy type not simply derive Clone as well rather than implement it manually.
3
u/The_Coalition 3d ago
Copy is always a byte-for-byte copy of the original, so it's always fast. It's not a marker type over Clone - you also can't force a non-copyable type to implement Copy, not even with unsafe.
4
u/buwlerman 4d ago
I'm surprised that that's possible. I'd have imagined there was some compiler magic that required the derived
Cloneimpl. At least there's a clippy warning for it.
3
2
u/tanoshikuidomouyo 4d ago edited 4d ago
You may be missing that 'for' introduces a pattern where you can deconstruct references.
So in your example: for &v in &self.some_vec { ... }
Excuse the formatting
1
3
u/This_Growth2898 4d ago
Are you looking for into_iter()?
2
u/LetsGoPepele 4d ago
No, because I only have a shared reference
&self, so I cannot movesome_vecout of&selfby callinginto_iter()1
-1
u/This_Growth2898 4d ago
When I've answered, you didn't say you have such a restriction. Next time, please, try to describe your situation in more detail to get better answers.
.copied()is there for a reason, and it looks like this is an exact situation when you need it. You have only borrowed values, and you need to copy them; that's what.copied()is about.1
u/LetsGoPepele 3d ago
Well... I did...
In a
&selfmethodBut yeah I agree my first post wasn't very clear. Thank you for your replies.
1
14
u/djvbmd 4d ago
Not sure why you dislike this style; it's the most concise / readable to me:
I'll move the deref to the pattern deconstruction in the for loop sometimes, though I don't feel like it's as explicit:
The version you're trying to get away from is probably the most explicit of all, but -- I agree -- annoying to write repeatedly. AFAIK there isn't any other ready-made syntax to do what you're doing.