Generic type parameters let you apply the code to different types. Traits and trait bounds ensure that even though the types are generic, they’ll have the behavior the code needs. You learned how to use lifetime annotations to ensure that this flexible code won’t have any dangling references.
fn main() {
let yummy_seeds = ("sunflower", "pumpkin");
let random_seeds = (42, 1234);
println!("Before swapping:");
println!("{} then {}", yummy_seeds.0, yummy_seeds.1);
println!("{} then {}", random_seeds.0, random_seeds.1);
// Swap their seeds using the type-specific functions
let yummy_seeds = swap_yummy_seeds(yummy_seeds);
let random_seeds = swap_random_seeds(random_seeds);
println!("\nAfter swapping:");
println!("{} then {}", yummy_seeds.0, yummy_seeds.1);
println!("{} then {}", random_seeds.0, random_seeds.1);
}
fn main() {
let yummy_seeds = ("sunflower", "pumpkin");
let random_seeds = (42, 1234);
println!("Before swapping:");
println!("{} then {}", yummy_seeds.0, yummy_seeds.1);
println!("{} then {}", random_seeds.0, random_seeds.1);
// Swap their habitats
let yummy_seeds = swap_seeds(yummy_seeds);
let random_seeds = swap_seeds(random_seeds);
println!("\nAfter swapping:");
println!("{} then {}", yummy_seeds.0, yummy_seeds.1);
println!("{} then {}", random_seeds.0, random_seeds.1);
}
fn main() {
// Define two animals and their habitats
let bird = ("Robin", "Forest");
let bat = ("Fruit Bat".to_string(), "Cave".to_string());
println!("Before swapping:");
println!("{} lives in the {}", bird.0, bird.1);
println!("{} lives in the {}", bat.0, bat.1);
// Swap their habitats
let (swapped_bird, swapped_bat) = swap_animals(bird, bat);
println!("\nAfter swapping:");
println!("{} now lives in the {}", swapped_bird.0, swapped_bird.1);
println!("{} now lives in the {}", swapped_bat.0, swapped_bat.1);
}
fn main() {
// Animal with a numeric ID
let chimpanzee = Animal {
name: String::from("Chimpanzee"),
id: 23,
};
// Animal with a string ID
let bonobo = Animal {
name: String::from("Bonobo"),
id: String::from("A-34"),
};
println!("{} {}", chimpanzee.name, chimpanzee.id);
println!("{} {}", bonobo.name, bonobo.id);
}
struct Bird {
name: String,
wingspan: u8,
}
impl Fly for Bird {
fn fly(&self) -> String {
format!(
"{} flaps its wings (wingspan: {} cm) and soars gracefully!",
self.name, self.wingspan
)
}
}
impl LayEggs for Bird {
fn lay_eggs(&self) -> String {
format!("{} lays eggs in its cozy nest!", self.name)
}
}
fn main() {
// Create a bird and a bat
let bird = Bird {
name: "Robin".to_string(),
wingspan: 30,
};
let bat = Bat {
name: "Fruit Bat".to_string(),
wingspan: 25,
};
fly_home(&bird, bird.wingspan, "nest");
fly_home(&bat, bat.wingspan, "cave");
// Uncommenting this line would cause a compilation error
// fly_home_and_lay_egg(&bat, bat.wingspan, "cave");
let bird2 = Bird {
name: "Eagle".to_string(),
wingspan: 200,
};
fly_home_and_lay_egg(&bird2, bird2.wingspan, "mountain nest");
}
Lifetimes are named regions of code that a reference must be valid for. —Rustnomicon
fn main() {
let lion = Predator {
ecosystem: String::from("savanna"),
};
let gazelle = Prey {
ecosystem: String::from("savanna"),
};
let deer = Prey {
ecosystem: String::from("forest"),
};
let result1 = describe_hunt(&lion, &gazelle);
let result2 = describe_hunt(&lion, &deer);
println!("Hunting scenario 1: {}", result1);
println!("Hunting scenario 2: {}", result2);
}
fn main() {
let ecosystem = Ecosystem {
name: String::from("Amazon Rainforest"),
biome: String::from("tropical rainforest"),
temperature: 26.7,
description: String::from("It is home to a vast array of plant and animal species."),
};
let predator = Animal {
name: String::from("Jaguar"),
ecosystem: &ecosystem,
};
let prey = Animal {
name: String::from("Capybara"),
ecosystem: &ecosystem,
};
println!("{}", predator.describe());
println!("{}", prey.describe());
}