X-Git-Url: https://git.ralfj.de/rust-101.git/blobdiff_plain/fff8ebeb3f0b84c71275cbb5adee0aad6114f79b..4fcb5d41bd72739b76beac0466a2dd59e403138b:/src/part06.rs diff --git a/src/part06.rs b/src/part06.rs index 35cd5a9..8161d2d 100644 --- a/src/part06.rs +++ b/src/part06.rs @@ -26,11 +26,11 @@ impl BigInt { } // Now we can write `vec_min`. -//@ However, in order to make it type-check, we have to make a full (deep) copy of e by calling `clone()`. fn vec_min(v: &Vec) -> Option { let mut min: Option = None; + // If `v` is a shared borrowed vector, then the default for iterating over it is to call `iter`, the iterator that borrows the elements. for e in v { - let e = e.clone(); /*@*/ + let e = e.clone(); min = Some(match min { /*@*/ None => e, /*@*/ Some(n) => e.min_try1(n) /*@*/ @@ -38,7 +38,7 @@ fn vec_min(v: &Vec) -> Option { } min } -//@ Now, what's happening here? Why do we have to clone `e`, and why did we not +//@ Now, what's happening here? Why do we have to to make a full (deep) copy of `e`, and why did we not //@ have to do that in our previous version? //@ //@ The answer is already hidden in the type of `vec_min`: `v` is just borrowed, but @@ -48,9 +48,9 @@ fn vec_min(v: &Vec) -> Option { //@ `e.clone()`, Rust will complain "Cannot move out of borrowed content". That's because //@ `e` is a `&BigInt`. Assigning `min = Some(*e)` works just like a function call: Ownership of the //@ underlying data is transferred from where `e` borrows from to `min`. But that's not allowed, since -//@ we just borrowed `e`, so we cannot empty it! We can, however, call `clone()` on it. Then we own -//@ the copy that was created, and hence we can store it in `min`.
-//@ Of course, making such a full copy is expensive, so we'd like to avoid it. We'll some to that in the next part. +//@ we just borrowed `e`, so we cannot empty it! We can, however, call `clone` on it. Then we own +//@ the copy that was created, and hence we can store it in `min`.
+//@ Of course, making such a full copy is expensive, so we'd like to avoid it. We'll come to that in the next part. // ## `Copy` types //@ But before we go there, I should answer the second question I brought up above: Why did our old `vec_min` work? @@ -78,7 +78,7 @@ impl Copy for SomethingOrNothing {} //@ ## An operational perspective //@ Instead of looking at what happens "at the surface" (i.e., visible in Rust), one can also explain -//@ ownership passing and how `Copy` and `Clone` fit in by looking at what happens on the machine.
+//@ ownership passing and how `Copy` and `Clone` fit in by looking at what happens on the machine.
//@ When Rust code is executed, passing a value (like `i32` or `Vec`) to a function will always //@ result in a shallow copy being performed: Rust just copies the bytes representing that value, and //@ considers itself done. That's just like the default copy constructor in C++. Rust, however, will @@ -92,7 +92,7 @@ impl Copy for SomethingOrNothing {} //@ `Clone`. This makes the cost explicit. // ## Lifetimes -//@ To fix the performance problems of `vec_min`, we need to avoid using `clone()`. We'd like +//@ To fix the performance problems of `vec_min`, we need to avoid using `clone`. We'd like //@ the return value to not be owned (remember that this was the source of our need for cloning), but *borrowed*. //@ The function `head` demonstrates how that could work: It borrows the first element of a vector if it is non-empty.