// in function definitionfn largest<T: PartialOrd + Copy>(list: &[T]) -> T { let mut largest = list[0]; for &item in list { if item > largest { largest = item; } } largest}fn main() { let number_list = vec![34, 50, 25, 100, 65]; let result = largest(&number_list); println!("The largest number is {}", result); let char_list = vec!['y', 'm', 'a', 'q']; let result = largest(&char_list); println!("The largest char is {}", result);}
// in struct definitionstruct Point<T> { x: T, y: T,}// in method definitionimpl<T> Point<T> { fn x(&self) -> &T { &self.x }}fn main() { let integer = Point { x: 5, y: 10 }; let float = Point { x: 1.0, y: 4.0 }; let p = Point { x: 5, y: 10 }; println!("p.x = {}", p.x());}
// in enum definitionenum Option<T> { Some(T), None,}
// returning types that implement traits// /!\ only possible to return a single type!// e.g. we cannot return either a `NewsArticle` or a `Tweet`fn returns_summarizable() -> impl Summary { Tweet { username: String::from("horse_ebooks"), content: String::from( "of course, as you probably already know, people", ), reply: false, retweet: false, }}
use std::fmt::Display;struct Pair<T> { x: T, y: T,}impl<T> Pair<T> { fn new(x: T, y: T) -> Self { Self { x, y } }}// conditionally implement methods on a generic type depending on trait boundsimpl<T: Display + PartialOrd> Pair<T> { fn cmp_display(&self) { if self.x >= self.y { println!("The largest member is x = {}", self.x); } else { println!("The largest member is y = {}", self.y); } }}
Validating references with lifetimes
// lifetime annotation syntax&i32 // a reference&'a i32 // a reference with an explicit lifetime&'a mut i32 // a mutable reference with an explicit lifetime
fn main() { let string1 = String::from("abcd"); let string2 = "xyz"; let result = longest(string1.as_str(), string2); println!("The longest string is {}", result);}// lifetime annotations in function signaturesfn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y }}
// lifetime annotations in struct definitionsstruct ImportantExcerpt<'a> { part: &'a str,}fn main() { let novel = String::from("Call me Ishmael. Some years ago..."); let first_sentence = novel.split('.').next().expect("Could not find a '.'"); let i = ImportantExcerpt { part: first_sentence, };}
// lifetime elision// same lifetime annotation => predictable => infer lifetimefn first_word(s: &str) -> &str { let bytes = s.as_bytes(); for (i, &item) in bytes.iter().enumerate() { if item == b' ' { return &s[0..i]; } } &s[..]}
// lifetime annotation in method definitionstruct ImportantExcerpt<'a> { part: &'a str,}impl<'a> ImportantExcerpt<'a> { fn level(&self) -> i32 { 3 }}impl<'a> ImportantExcerpt<'a> { fn announce_and_return_part(&self, announcement: &str) -> &str { println!("Attention please: {}", announcement); self.part }}fn main() { let novel = String::from("Call me Ishmael. Some years ago..."); let first_sentence = novel.split('.').next().expect("Could not find a '.'"); let i = ImportantExcerpt { part: first_sentence, };}
// static lifetime: reference can live for the entire duration of the programlet s: &'static str = "I have a static lifetime.";