X-Git-Url: https://git.ralfj.de/rust-101.git/blobdiff_plain/6a1e87efaf3398aa56c8a52891b7edbb32c5d301..0da6e9205576b3191f45190a18d1f7d1e33fb0ea:/src/part06.rs?ds=sidebyside diff --git a/src/part06.rs b/src/part06.rs index 04601ba..4c7ee24 100644 --- a/src/part06.rs +++ b/src/part06.rs @@ -56,7 +56,6 @@ fn vec_min(v: &Vec) -> Option { //@ 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? We stored the minimal `i32` locally without cloning, and Rust did not complain. //@ That's because there isn't really much of an "ownership" when it comes to types like `i32` or @@ -71,6 +70,7 @@ fn vec_min(v: &Vec) -> Option { //@ must also implement `Copy`, and that's why the compiler accepted our generic `vec_min` in part //@ 02. `Copy` is the first *marker trait* that we encounter: It does not provide any methods, but //@ makes a promise about the behavior of the type - in this case, being duplicable. + //@ If you try to implement `Copy` for `BigInt`, you will notice that Rust does not let you do //@ that. A type can only be `Copy` if all its elements are `Copy`, and that's not the case for //@ `BigInt`. However, we can make `SomethingOrNothing` copy if `T` is `Copy`. @@ -100,6 +100,7 @@ impl Copy for SomethingOrNothing {} //@ 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*. In other words, we want to return a shared reference to the minimal element. + //@ The function `head` demonstrates how that could work: It returns a reference to the first //@ element of a vector if it is non-empty. The type of the function says that it will either //@ return nothing, or it will return a borrowed `T`. We can then obtain a reference to the first @@ -126,8 +127,8 @@ fn head(v: &Vec) -> Option<&T> { //@ have aliasing (of `first` and `v`) and mutation. But this time, the bug is hidden behind the //@ call to `head`. How does Rust solve this? If we translate the code above to Rust, it doesn't //@ compile, so clearly we are good - but how and why? -//@ (Notice that have to explicitly assert using //@ `unwrap` that `first` is not `None`, whereas -//@ the C++ code above would silently dereference a //@ `NULL`-pointer. But that's another point.) +//@ (Notice that we use `unwrap` to explicitly assert that `first` is not `None`, whereas +//@ the C++ code above would silently dereference a `NULL`-pointer. But that's another point.) fn rust_foo(mut v: Vec) -> i32 { let first: Option<&i32> = head(&v); /* v.push(42); */ @@ -158,11 +159,10 @@ fn rust_foo(mut v: Vec) -> i32 { //@ references into data they got as argument, and make sure they are used correctly, *while //@ looking only at the function type*. At no point in our analysis of `rust_foo` did we have to //@ look *into* `head`. That's, of course, crucial if we want to separate library code from -//@ application code. -//@ Most of the time, we don't have to explicitly add lifetimes to function types. This is thanks -//@ to *lifetime elision*, where Rust will automatically insert lifetimes we did not specify, -//@ following some simple, well-documented -//@ [rules](https://doc.rust- lang.org/stable/book/lifetimes.html#lifetime-elision). +//@ application code. Most of the time, we don't have to explicitly add lifetimes to function +//@ types. This is thanks to *lifetime elision*, where Rust will automatically insert lifetimes we +//@ did not specify, following some simple, well-documented +//@ [rules](https://doc.rust-lang.org/stable/book/lifetimes.html#lifetime-elision). //@ [index](main.html) | [previous](part05.html) | [raw source](workspace/src/part06.rs) | //@ [next](part07.html)