Skip to content

Commit 1ef8dac

Browse files
jaybermanyinsects
authored andcommitted
feat: add lifetimes exercises
1 parent 1cc5df0 commit 1ef8dac

File tree

5 files changed

+114
-0
lines changed

5 files changed

+114
-0
lines changed

exercises/lifetimes/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Lifetimes
2+
3+
Lifetimes tell the compiler how to check whether references live long
4+
enough to be valid in any given situation. For example lifetimes say
5+
"make sure parameter 'a' lives as long as parameter 'b' so that the return
6+
value is valid".
7+
8+
They are only necessary on borrows, i.e. references,
9+
since copied parameters or moves are owned in their scope and cannot
10+
be referenced outside. Lifetimes mean that calling code of e.g. functions
11+
can be checked to make sure their arguments are valid. Lifetimes are
12+
restrictive of their callers.
13+
14+
## Further information
15+
16+
- [Validating References with Lifetimes](https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html)
17+
- [Lifetimes (in Rust By Example)](https://doc.rust-lang.org/stable/rust-by-example/scope/lifetime.html)

exercises/lifetimes/lifetimes1.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// lifetimes1.rs
2+
//
3+
// The Rust compiler needs to know how to check whether supplied references are
4+
// valid, so that it can let the programmer know if a reference is at risk
5+
// of going out of scope before it is used. Remember, references are borrows
6+
// and do not own their own data. What if their owner goes out of scope?
7+
//
8+
// Execute `rustlings hint lifetimes1` or use the `hint` watch subcommand for a hint.
9+
10+
// I AM NOT DONE
11+
12+
fn longest(x: &str, y: &str) -> &str {
13+
if x.len() > y.len() {
14+
x
15+
} else {
16+
y
17+
}
18+
}
19+
20+
fn main() {
21+
let string1 = String::from("abcd");
22+
let string2 = "xyz";
23+
24+
let result = longest(string1.as_str(), string2);
25+
println!("The longest string is {}", result);
26+
}

exercises/lifetimes/lifetimes2.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// lifetimes2.rs
2+
//
3+
// So if the compiler is just validating the references passed
4+
// to the annotated parameters and the return type, what do
5+
// we need to change?
6+
//
7+
// Execute `rustlings hint lifetimes2` or use the `hint` watch subcommand for a hint.
8+
9+
// I AM NOT DONE
10+
11+
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
12+
if x.len() > y.len() {
13+
x
14+
} else {
15+
y
16+
}
17+
}
18+
19+
fn main() {
20+
let string1 = String::from("long string is long");
21+
let result;
22+
{
23+
let string2 = String::from("xyz");
24+
result = longest(string1.as_str(), string2.as_str());
25+
}
26+
println!("The longest string is {}", result);
27+
}

exercises/lifetimes/lifetimes3.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// lifetimes3.rs
2+
//
3+
// Lifetimes are also needed when structs hold references.
4+
//
5+
// Execute `rustlings hint lifetimes3` or use the `hint` watch subcommand for a hint.
6+
7+
// I AM NOT DONE
8+
9+
struct Book {
10+
author: &str,
11+
title: &str,
12+
}
13+
14+
fn main() {
15+
let name = String::from("Jill Smith");
16+
let title = String::from("Fish Flying");
17+
let book = Book { author: &name, title: &title };
18+
19+
println!("{} by {}", book.title, book.author);
20+
}

info.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,30 @@ You can call a function right where you're passing arguments to `assert!` -- so
746746
something like `assert!(having_fun())`. If you want to check that you indeed get false, you
747747
can negate the result of what you're doing using `!`, like `assert!(!having_fun())`."""
748748

749+
# LIFETIMES
750+
751+
[[exercises]]
752+
name = "lifetimes1"
753+
path = "exercises/lifetimes/lifetimes1.rs"
754+
mode = "compile"
755+
hint = """
756+
Let the compiler guide you. Also take a look at the book if you need help:
757+
https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html"""
758+
759+
[[exercises]]
760+
name = "lifetimes2"
761+
path = "exercises/lifetimes/lifetimes2.rs"
762+
mode = "compile"
763+
hint = """
764+
What is the compiler checking? How could you change how long an owned variable lives?"""
765+
766+
[[exercises]]
767+
name = "lifetimes3"
768+
path = "exercises/lifetimes/lifetimes3.rs"
769+
mode = "compile"
770+
hint = """
771+
If you use a lifetime annotation in a struct's fields, where else does it need to be added?"""
772+
749773
# STANDARD LIBRARY TYPES
750774

751775
[[exercises]]

0 commit comments

Comments
 (0)