From e840d912d13dc93ce3167b29e60ab25885556c3a Mon Sep 17 00:00:00 2001 From: Rowan Torbitzky-Lane Date: Fri, 28 Mar 2025 18:41:16 -0500 Subject: [PATCH] finish ch10 --- ch10/traits/src/main.rs | 49 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/ch10/traits/src/main.rs b/ch10/traits/src/main.rs index 770cb46..3692083 100644 --- a/ch10/traits/src/main.rs +++ b/ch10/traits/src/main.rs @@ -3,6 +3,8 @@ // behavior in an abstract way. Can use trait bounds to specify // that a generic type can be any type that has certain behavior +use std::fmt::Display; + // Like Haskell's deriving // Except orphans aren't allowed at all pub trait Summary { @@ -89,6 +91,10 @@ fn main() { } // println!("The longest string is {result}"); + + // the static lifetime + // Can life for the duration of the program + let s: &'static str = "I have a static lifetime"; } // fn notify(item1: &T, item2: &T) {} @@ -109,6 +115,7 @@ where // <'a> and 'a dispersed in the function parameters are // lifetime annotations. Lifetimes annotations are needed because // Rust can't tell whether the reference being returned refers to x or y +// Feels like a similar vibe to Haskell `forall a`. fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x @@ -121,6 +128,44 @@ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { // with references passed as a parameter have lifetime annotations // passed implicitly due to soooooo many functions having this // lifetime annotation pattern used. +// +// Lifetimes on function/method parameters called input lifetimes. +// Lifetimes on return values output lifetimes +// +// 3 Rules for lifetime functions +// 1: Compiler assigns different lifetime parameter to each lifetime +// in each input type +// fn foo(x: &i32) becomes fn foo<'a>(x: &'a i32) +// fn foo(x: &i32, y: &i32) becomes fn foo<'a, 'b>(x: &'a i32, y: &'b i32) +// fn foo(x: &ImportantExcerpt) becomes fn foo<'a, 'b>(x: &'a ImportantExcerpt<'b>) +// 2: If exactly one input lifetime paramter, lifetime applied to all output +// lifetime parameters +// 3: If multiple input lifetime parameters, but one of them is &self or &mut self, +// lifetime of self assigned to all output lifetime parameters -// Stopped here pre red river gorge: -// https://rust-book.cs.brown.edu/ch10-03-lifetime-syntax.html#lifetime-elision +// Lifetime annotations in method definitions + +impl<'a> ImportantExcerpt<'a> { + fn level(&self) -> i32 { + 3 + } + + // example of third lifetime elision rule + fn announce_and_return_part(&self, announcement: &str) -> &str { + println!("Attention Please: {announcement}"); + self.part + } +} + +// Generic Type Paramters, trait bounds, and lifetimes together +fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str +where + T: Display, +{ + println!("Announcement!: {ann}"); + if x.len() > y.len() { + x + } else { + y + } +}