In Rust, generics are a powerful feature that enables programmers to write more flexible and reusable code. They are primarily used to minimize code duplication and handle various data types without writing repetitive code for each type.
Basic Usage of Generics
Rust supports generics across functions, structs, enums, and methods. Below are simple examples demonstrating their usage.
1. Generic Functions
Generic functions allow identical code logic to operate on different data types. For instance, we can create a generic function to swap two values:
rustfn swap<T>(a: &mut T, b: &mut T) { let temp = std::mem::replace(a, std::mem::take(b)); *b = temp; } fn main() { let mut x = 5; let mut y = 10; swap(&mut x, &mut y); println!("x: {}, y: {}", x, y); // Output: x: 10, y: 5 }
Here, <T> denotes the generic type parameter, allowing the swap function to work with any type.
2. Generic Structs
Generics can be applied to structs, enabling them to adapt to various data types. For example, we can define a generic Pair struct with two elements:
ruststruct Pair<T> { first: T, second: T, } fn main() { let pair_of_ints = Pair { first: 1, second: 2 }; let pair_of_floats = Pair { first: 1.0, second: 2.0 }; println!("ints: ({}, {})", pair_of_ints.first, pair_of_ints.second); println!("floats: ({}, {})", pair_of_floats.first, pair_of_floats.second); }
3. Generic Enums
Rust enums also support generics. Common examples include Option<T> and Result<T, E>:
rustenum Option<T> { Some(T), None, } enum Result<T, E> { Ok(T), Err(E), }
This allows Option or Result to handle diverse data types effectively.
4. Generic Methods and Generics in impl Blocks
Generics can be used in method definitions for structs or enums, as well as within impl blocks:
ruststruct Point<T> { x: T, y: T, } impl<T> Point<T> { fn x(&self) -> &T { &self.x } } fn main() { let int_point = Point { x: 5, y: 10 }; println!("Point x: {}", int_point.x()); }
Conclusion
As illustrated by these examples, Rust's generics are highly flexible, enabling code that adapts to various data types. This increases reusability while minimizing redundancy, significantly enhancing Rust's expressiveness and safety.