Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 9, 2022 11:44 am GMT

Rust Generics

It is a way of writing generalised algorithms in such a way that can be used for the types specified later. It can be initialised for a specified type with help of parameters.

What we use generics:-

  1. Abstract Types: Instead of writing explicit type like i32 or float we can use the generics for different types by writing different code
  2. Adds Flexibility: We can use different data types with the same piece of code.
  3. Reduces Code Duplication: We can have the same piece of code or both for any two types.
  4. No Runtime Cost: Unlike Object Traits, generics don't have runtime costs. The compiler generates the different types in the background during compile time.

Rust Generics Meme

Let's get started

Usually the generics type parameter is represented by <T>. But you are free to use any.

Structs

1. Single placeholder type

Defining the struct with the placeholder/generic type.

struct Point<T> {    x: T,    y: T,}

Let's try to use this for i32

pub fn main() {    let i32_point = Point { x: 45, y: 90 };    println!("x is {} and y is {}", i32_point.x, i32_point.y);}

If you hover on the i32_point then you can find the type of variable is Point i32 i32. But it is not limited. You can even use the float for both x and y but they must be the same.

So how can we use the different types for the two fields x and y?

It can be done using the two placeholder

2. Two placeholder

struct definition

struct TwoPoint<T, U> {    x: T,    y: U,}

let's test

pub fn main() {    let explicit_point = TwoPoint { x: 9, y: 90.3 };    println!(        "explicit_point x is {} and y is {}",        explicit_point.x, explicit_point.y    );}

Similarly we can two different data types for the x and y, even vectors.

Enums

1. Generics with Enum

creating a result enum that will store the result whether pass, fail, or awaiting.

#[derive(Debug)]enum Result<T> {    Passed(T),    Failed(T),    Pending,}

Used the Debug trait because the enum is not primitive because all the primitives include the debug capabilities/trait.

Testing

pub fn main() {  let result = Result::Passed(43);  match result {      Result::Passed(a) => println!("Student Passed with {}", a),      Result::Failed(b) => println!("Student Failed with {}", b),      Result::Pending => println!("Student result is pending"),  }}

You can use different generics types for Passed and Failed as shown in the above case.

2. Using struct and enums together with generics

we are using the Result enum from the above example

struct Student<T> {    name: String,    roll_no: T,    result: Result<T>,}

Let's use it

pub fn main() {  let student = Student {      name: "Praveen".to_string(),      roll_no: 78,      result: Result::Passed(98),  };  match student.result {      Result::Passed(a) => println!("Student Passed with {}", a),      Result::Failed(b) => println!("Student Failed with {}", b),      Result::Pending => println!("Student result is pending"),  }}

Functions with Generics

1. Function with single generic type parameter and single trait

function definition

fn custom_add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {    a + b}

Here Output=T ensures that after the + or - result must be the same. It can be different if you wish too like the addition of two atoms can result in the molecule(T+T=U)

let a = 4;let b = 5;println!("sum of {} and {} is {}", a, b, custom_add(a, b));

2. Function with single generic type parameter and multiple traits

fn custom_add_sub<T: std::ops::Add<Output = T> + std::ops::Sub<Output = T> + std::fmt::Debug>(    a: T,    b: T,) -> T {    // Debug trait is needed for this print statement    println!("{:?} {:?}", a, b);    a + b}

Using the type

pub fn main() {  println!("sub of {} and {} is {}", a, b, custom_add_sub(a, b));}

I know it's easy for you now

3.Function with multiple generic type parameters and multiple traits and where keyword

// using the where to define a generic typefn custom_add_sub_mul<T, E>(a: T, b: T, c: E) -> Twhere    T: std::ops::Mul<Output = T> + std::ops::Add<Output = T> + std::ops::Sub<Output = T>,    E: std::fmt::Debug,{    println!("{:?}", c);    a * b}

where keyword makes our code clearer. It doesn't have any impact on how the code run.

pub fn main() {  println!("mul of {} and {} is {}", a, b, custom_add_sub_mul(a, b, b));}

4. Functions with custom trait

Instead of using the predefined trait, we can use the custom trait as we like to.

trait SomeCustomTrait {    fn bla_bla(&self, a: &str, b: &str) -> String;}#[derive(Debug)]struct TestStruct {    something: i32,}impl SomeCustomTrait for TestStruct {    fn bla_bla(&self, a: &str, b: &str) -> String {        self.something.to_string() + "-" + a + "-" + b    }}fn do_this<T>(some_var: &T) -> Stringwhere    T: SomeCustomTrait + std::fmt::Debug,{    println!("{:?}", some_var);    some_var.bla_bla("first", "second")}

In the function, we have used our SomeCustomTrait along with the Debug. We can even add more.

pub fn main() {  let test = TestStruct { something: 1000 };  let result = do_this(&test);}

Impl with Generics

struct ImplStruct<T, U> {    field1: T,    field2: U,}impl<T, U> ImplStruct<T, U>where    T: std::fmt::Debug,    U: std::fmt::Debug,{    fn log_something(&self) {        println!("{:?} {:?}", self.field1, self.field2);    }}

You can notice here the generics type is defined at the impl block instead of a struct but you can define it at both blocks but Impl block is a must.

pub fn main() {  let impl_test = ImplStruct{      field1:5.6,      field2:vec![1,2,3],  };  impl_test.log_something();

So, we have covered the basics of Rust Generics but you can do a lot more with Generics.

Resources

  1. rust-lang by example
  2. Doug MilfordSource codeRustyRustLessons Generics

Happy Hacking
Rustaceans!


Original Link: https://dev.to/chaudharypraveen98/rust-generics-c11

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To