Skip to content

Generics and trait bounds

Generics in Rust are a way to write flexible, reusable, and type-safe code. They allow you to define functions, structs, enums, or methods that can operate on different types of data, without knowing the exact types ahead of time. Instead of specifying a concrete type, you can use a placeholder that will be replaced by a specific type when the code is compiled.

Create a first_element function

pub fn main() {
let v = vec![1, 2, 3];
let v2 = vec![String::from("Harkirat"), String::from("Singh")];
let v3 = vec![1.0, 2.0, 3.0];
println!("{}", first_element(v).unwrap());
println!("{}", first_element(v2).unwrap());
println!("{}", first_element(v3).unwrap());
}
fn first_element<T>(v: Vec<T>) -> Option<T> {
return v.into_iter().nth(0);
}

Create a does_exist function (trait bound)

pub fn main() {
let v = vec![1, 2, 3];
let v2 = vec![String::from("Harkirat"), String::from("Singh")];
let v3 = vec![1.0, 2.0, 3.0];
println!("{}", first_element(v.clone()).unwrap());
println!("{}", first_element(v2).unwrap());
println!("{}", first_element(v3).unwrap());
println!("{}", does_exist(v, 1));
}
fn first_element<T>(v: Vec<T>) -> Option<T> {
return v.into_iter().nth(0);
}
fn does_exist<T: std::cmp::PartialEq>(v: Vec<T>, element: T) -> bool {
let mut iter = v.iter();
while let Some(value) = iter.next() {
if *value == element {
return true;
}
}
return false;
}

Create a biggest_element function

fn biggest_element<T: Ord>(a: T, b: T) -> T {
if a > b {
return a;
}
return b;
}

Create a print_variable function

use std::fmt::Display;
fn print_variable<T: Display>(a: T) {
println!("{}", a);
}