Theoretical Paper
- Computer Organization
- Data Structure
- Digital Electronics
- Object Oriented Programming
- Discrete Mathematics
- Graph Theory
- Operating Systems
- Software Engineering
- Computer Graphics
- Database Management System
- Operation Research
- Computer Networking
- Image Processing
- Internet Technologies
- Micro Processor
- E-Commerce & ERP
- Dart Programming
- Flutter Tutorial
- Numerical Methods Tutorials
- VueJS
- Go
Practical Paper
Industrial Training
Rust Generics
When we want to create the function of multiple forms, i.e., the parameters of the function can accept the multiple types of data. This can be achieved through generics. Generics are also known as 'parametric polymorphism' where poly is multiple, and morph is form.
There are two ways to provide the generic code:
-
Option< T>
Result< T, E>
1. Option< T>: Rust standard library provides Option where 'T' is the generic data type. It provides the generic over one type.
enum Option< T> { Some(T), None, }
In the above case, enum is the custom type where In the above case, we observe that 'T' can be of any type, i.e., i32, bool, f64 or char. But, if the type on the left-hand side and the value on the right hand side didn't match, then the error occurs. Let's look at this: In the above case, type on the left-hand side is i32, and the value on the right-hand side is of type f64. Therefore, the error occurs "type mismatched". 2. Result< T,E>: Rust standard library provides another data type Result< T,E> which is generic over two type, i.e., T &E: Note: It is not a convention that we have to use 'T' and 'E'. We can use any capital letter. Generics can be used in the functions, and we place the generics in the signature of the function, where the data type of the parameters and the return value is specified. Structs can also use the generic type parameter in one or more fields using <> operator. In the above syntax, we declare the generic type parameter within the angular brackets just after the structure_name, and then we can use the generic type inside the struct definition. In the above example, Value< T> struct is generic over one type and a and b are of the same type. We create two instances integer and float. Integer contains the values of type i32 and float contains the values of type f64. In the above example, Value< T> struct is generic over one type, and a and b are of the same type. We create an instance of 'c'. The 'c' contains the value of different types, i.e., i32 and f64. Therefore, the Rust compiler throws the "mismatched error". An enum can also use the generic data types.Rust standard library provides the Option< T> enum which holds the generic data type. The Option< T> is an enum where 'T' is a generic data type. It consists of two variants, i.e., Some(T) and None. Where Some(T) holds the value of type T and None does not contain any value. In the above case, Option is an enum which is generic over one type 'T'. It consists of two variants Some(T) and None. In the above case, Result< T, E> is an enum which is generic over two types, and it consists of two variants, i.e., OK(T) and Err(E). We can implement the methods on structs and enums. In the above example, we have implemented the method named as 'a' on the Program< T> that returns a reference to the data present in the variable a. Rust compiler automatically infers the generic parameters. Let's understand this through a simple scenario: In the above case, we insert the integer value into the vector. Therefore, the Rust compiler got to know that the vector v has the type i32. The above case will throw an error that "it cannot infer the type for T". 1. We can use the following annotation: 2. We can bind the generic parameter 'T' by using the 'turbofish' ::<> operator:
let x : Option< i32> = Some(10); // 'T' is of type i32.
let x : Option< bool> = Some(true); // 'T' is of type bool.
let x : Option< f64> = Some(10.5); // 'T' is of type f64.
let x : Option< char> = Some('b'); // 'T' is of type char.
let x : Option< i32> = Some(10.8);
enum Result
Generic functions
When the function contains a single argument of type 'T'.
Syntax:
fn function_name< T>(x:T)
// body of the function.
The above syntax has two parts:
< T> : The given function is a generic over one type.
(x : T) : x is of type T.
When the function contains multiple arguments of the same type.
fn function_name
When the function contains arguments of multiple types.
fn function_name
fn main()
{
let a = vec![1,2,3,4,5];
let b = vec![2.3,3.3,4.3,5.3];
let result = add(&a);
let result1 = add(&b);
println!("The value of result is {}",result);
println!("The value of result1 is {}",result1);
}
fn add
Struct Definitions
Syntax:
struct structure_name< T>
// Body of the structure.
Let's see a simple example:
struct Value
Output:
integer values : 2,3
Float values : 7.8,12.3
Let's see another simple example.
struct Value< T>
{
a:T,
b:T,
}
fn main()
{
let c = Value{a:2,b:3.6};
println!("c values : {},{}",c.a,c.b);
}
Output:
Enum Definitions
Option< T>
Let's look:
enum Option< T>
{
Some(T),
None,
}
Result< T, E>: We can create the generic of multiple types. This can be achieved through Result< T, E>.
enum Result< T,E>
{
OK(T),
Err(E),
}
OK(T) holds the value of type 'T' while Err(E) holds the value of type 'E'.
Method Definitions
Let's see a simple example:
struct Program< T> {
a: T,
b: T,
}
impl< T> Program< T>
{
fn a(&self) -> &T
{
&self.a
}
}
fn main() {
let p = Program{ a: 5, b: 10 };
println!("p.a() is {}", p.a());
}
Output:
p.a() is 5
We have declared the 'T' after impl to specify that we are implementing the method on Program< T>.
Resolving Ambiquities
Let mut v = Vec::new(); // creating a vector.
v.push(10); // inserts integer value into the vector. Therefore, v is of i32 type.
println!("{:?}", v); // prints the value of v.
If we delete the second last line, then it looks like;
Let mut v = Vec::new(); // creating a vector.
println!("{:?}", v); // prints the value of v.
We can solve the above case in two ways:
let v : Vec< bool> = Vec::new();
println!("{:?}",v) ;
let v = Vec :: < bool> :: new();
println!("{:?}",v) ;