Enjoy Day 4
Now we need enum
to replace "cat" and "duck" type from previous example.
Enum
You also can impl
to enum
👇.
#[derive(Debug)] enum AnimalType { Cat, Duck, } // How to return string or &str from enum. impl AnimalType { fn as_str(&self) -> &str { match self { AnimalType::Cat => "🐈", AnimalType::Duck => "🐥", } } // How to use type as a parameters, but hey!👇 what's this? 😳 fn say1(animal_type: AnimalType) -> &'static str { // To survive from fn {}, we need 👆 'static to let is has program's lifetime. match animal_type { AnimalType::Cat => "meaowww", AnimalType::Duck => "quackkk", } } // But why this didn't need to add static here? 👇 😳 fn say2(&self, animal_type: AnimalType) -> &str { match animal_type { AnimalType::Cat => "meaowww", AnimalType::Duck => "quackkk", } } // That's because `elided lifetime rules` cover that for you already! // Then👇 you👇 don't need to write this loooooong👇 fn say3<'a>(&'a self, animal_type: AnimalType) -> &'a str { match animal_type { AnimalType::Cat => "meaowww", AnimalType::Duck => "quackkk", } } // Remember this? fn static_say1(animal_type: &str) -> &str { match animal_type { "cat" => "meaowww", "duck" => "quackkk", _ => "wat!", } } // Actually the longer one look like this fn static_say2<'a>(animal_type: &'a str) -> &'a str { match animal_type { "cat" => "meaowww", "duck" => "quackkk", _ => "wat!", } } } fn main() { println!( "{0:?} aka {1:?} say {2:?}, {3:?}", AnimalType::Cat, AnimalType::Cat.as_str(), AnimalType::say1(AnimalType::Cat), AnimalType::say2(&AnimalType::Cat, AnimalType::Cat), ); }
💡 There's more examples about Enums, and match enums.
Don't worry about &'static str
or lifetimes
just yet, compiler will let you know when need (usually out of { }
scope ) and we will talk about it later. Let's continue on other topics.
strum
Install
cargo add strum
cargo add strum_macros
and get
strum = "0.26"
strum_macros = "0.26"
or
cargo add strum --features=derive
and get
strum = { version = "0.26", features = ["derive", "strum_macros"] }
use std::str::FromStr; use strum_macros::{Display, EnumString}; #[derive(Debug, Eq, PartialEq, EnumString, Display)] enum AnimalType { #[strum(serialize = "cat", to_string = "catty")] Cat, #[strum(serialize = "duck", to_string = "ducky")] Duck, Unknown, #[strum(disabled)] Pet(String), } #[derive(Debug, Eq, PartialEq, EnumString, Display)] enum AnimalSound { #[strum(serialize = "cat", to_string = "meaowww")] Cat, #[strum(serialize = "duck", to_string = "quackkk")] Duck, } fn main() { // Get AnimalType from &str. let animal_type = AnimalType::from_str("cat"); println!("1️⃣ animal_type: {animal_type:?}"); // Unwrap or assign as Unknown. let animal_type = animal_type.unwrap_or(AnimalType::Unknown).to_string(); println!("2️⃣ animal_type: {animal_type:?}"); // Get AnimalSound from str. let cat_sound_result = AnimalSound::from_str("cat"); println!("3️⃣ cat_sound_result: {:?}", cat_sound_result); // Handle cat_sound Result. let cat_sound_string = match cat_sound_result { // Handle happy case. Ok(animal_sound) => animal_sound.to_string(), // Handle error case. Err(err) => panic!("{:?}", err), }; println!("4️⃣ cat_sound_string: {cat_sound_string:?}"); // 😱 Uncomment this to experience an error and try to fix it by add Clone, Copy to AnimalSound // println!("4️⃣ cat_sound_result: {cat_sound_result:?}"); // Match let animals = vec![AnimalType::Cat, AnimalType::Pet("snoopy".to_owned())]; let my_pet = animals .into_iter() .filter_map(|e| match e { AnimalType::Pet(name) => Some(name), AnimalType::Cat => None, AnimalType::Duck => None, AnimalType::Unknown => None, }) .collect::<Vec<_>>(); println!("5️⃣ my_pet: {:?}", my_pet.join(",")); }
🤷
strum
is not runnable via Rust Playground so output is shown below.
Run
1️⃣ animal_type: Ok(Cat)
2️⃣ animal_type: "catty"
3️⃣ cat_sound_result: Ok(Cat)
4️⃣ cat_sound_string: "meaowww"
5️⃣ my_pet: "snoopy"