Lifetimes
Sorting an immutable collection of strings
Let us assume that we want to write a function which sorts an immutable collection of String
elements. Here, "immutable" means that we cannot modify either the strings or the collection itself. We will have to return a Vec
containing the result.
Exercise 2.a: write a function sorted
which takes a reference to a slice of String
instances and return a Vec<String>
with the sorted strings.
The function will have the following signature:
#![allow(unused)] fn main() { fn sorted(names: &[String]) -> Vec<String> { todo!() // Write the code here } }
You can use the following constructs to help you to so:
vec![]
creates an emptyVec
(the type of the elements will be deduced from the context).- If
s
is aString
(or a&String
),s.clone()
will produce a newString
with the same content ass
. - You can iterate over the content of a slice
names
of type&[String]
withfor name in names { … }
.name
will have type&String
within the loop. - You can use
.sort()
on a mutable slice: it will sort your elements in the natural order.
You can test your function with the following main
program:
fn main() { let people = [String::from("John Doe"), String::from("Jane Eyre"), String::from("Jane Doe")]; let in_order = sorted(&people); for n in in_order { println!("- {n}"); } }
This should print "Jane Doe", "Jane Eyre", and "John Doe" in order.
Avoiding cloning the strings
While the previous program works, you had to clone the immutable strings. This is unfortunate as this consumes more memory. Why not work directly with a Vec
of &String
and sort it?
Exercise 2.b: modify your sorted
function so that it returns a Vec<&String>
instead of a Vec<String>
.
Note that .sort()
will work on a collection of &String
: it will sort them the same way it sorted String
elements.
Testing the guarantees of lifetimes
The signature of your sorted
function is:
#![allow(unused)] fn main() { fn sorted(names: &[String]) -> Vec<&String> }
Since you have not indicated any explicit lifetime (remember, lifetimes start with a single tick character '
), lifetimes elision kicked in: the lifetime of the &[String]
slice was copied over the &String
elements inside the Vec
.
It means that the result of sorted()
cannot live longer than its argument names
.
Exercise 2.c: experiment with the following modified main program, which will not compile, and make sure you understand why the compiler is telling you that you cannot store the output of sorted(&people)
into in_order
. Note how it prevents you from referencing strings that have been destroyed when people
went out of scope. You would not have had any such guarantee in C.
fn main() { let in_order = { let people = [String::from("John Doe"), String::from("Jane Eyre"), String::from("Jane Doe")]; sorted(&people) }; for n in in_order { println!("- {n}"); } }