📖 Scenario: Imagine you want to write a function that can work with different types of data, like numbers or text, without rewriting the same code for each type.
🎯 Goal: You will build a simple Rust program that shows how generics let you write one function to handle multiple data types safely and easily.
📋 What You'll Learn
Create a function that adds two numbers of type i32
Create a function that adds two numbers of type f64
Create a generic function that adds two values of any type that supports addition
Print the results of calling each function
💡 Why This Matters
🌍 Real World
Generics are used in real programs to write flexible and reusable code, like collections that hold any type of data.
💼 Career
Understanding generics is important for Rust developers to write efficient, safe, and maintainable software.
Progress0 / 4 steps
1
Create two functions for adding numbers
Write a function called add_i32 that takes two i32 numbers and returns their sum. Also write a function called add_f64 that takes two f64 numbers and returns their sum.
Rust
Hint
Define two separate functions with the exact names add_i32 and add_f64. Each should return the sum of its two parameters.
2
Create a generic function for addition
Write a generic function called add_generic that takes two parameters of the same type T and returns their sum. Use the trait bound T: std::ops::Add to allow addition.
Rust
Hint
Use fn add_generic<T: std::ops::Add<Output = T>>(a: T, b: T) -> T and return a + b.
3
Call all three functions with example values
Call add_i32 with 5 and 10, call add_f64 with 1.5 and 2.5, and call add_generic with 3 and 7. Store the results in variables sum_i32, sum_f64, and sum_generic respectively.
Rust
Hint
Use let to store the results of calling each function with the exact values given.
4
Print the results
Print the values of sum_i32, sum_f64, and sum_generic each on its own line using println!.
Rust
Hint
Use println!("{}", variable); to print each sum on its own line.
Practice
(1/5)
1. Why do we use generics in Rust? fn print_value<T>(value: T) {}
easy
A. To limit functions to only one type of data
B. To write functions that work with many types without repeating code
C. To make the code run faster by using specific types only
D. To avoid using variables inside functions
Solution
Step 1: Understand the purpose of generics
Generics allow writing one function that can accept many types instead of writing many functions for each type.
Step 2: Analyze the example function
The function print_value<T> uses a placeholder T to accept any type, showing flexibility.
Final Answer:
To write functions that work with many types without repeating code -> Option B
Quick Check:
Generics = flexible reusable code [OK]
Hint: Generics = one code fits many types [OK]
Common Mistakes:
Thinking generics make code faster
Believing generics restrict types
Confusing generics with variables
2. Which of the following is the correct syntax to define a generic function in Rust?
easy
A. fn example<T>(value T) {}
B. fn example(value: T) {}
C. fn example<T> value: T {}
D. fn example<T>(value: T) {}
Solution
Step 1: Recall Rust generic function syntax
Generic functions use angle brackets <T> after the function name to declare type parameters.
Step 2: Check each option
fn example<T>(value: T) {} correctly uses fn example<T>(value: T) {}. Others miss brackets or have wrong parameter syntax.
Final Answer:
fn example<T>(value: T) {} -> Option D
Quick Check:
Generic syntax = fn name<T>(param: T) [OK]
Hint: Generic syntax always uses <T> after function name [OK]
The generic type T requires the Display trait to print values with {}.
Step 2: Check calls with different types
Calling print_type(10) prints "Value: 10" and print_type("hello") prints "Value: hello" because both implement Display.
Final Answer:
Value: 10
Value: hello -> Option C
Quick Check:
Generics with Display trait print all types correctly [OK]
Hint: Generics with Display print any printable type [OK]
Common Mistakes:
Assuming generic needs no trait bound
Expecting same output for different inputs
Confusing compile and runtime errors
4. Identify the error in this Rust code using generics:
fn add<T>(a: T, b: T) -> T {
a + b
}
fn main() {
println!("{}", add(5, 10));
}
medium
A. Missing trait bound for + operator on T
B. Wrong return type declared
C. Function parameters should be references
D. Cannot use println! with generic functions
Solution
Step 1: Check operator usage on generic type
The + operator requires the type T to implement the Add trait.
Step 2: Identify missing trait bound
The function lacks T: std::ops::Add<Output = T> bound, causing a compile error.
Final Answer:
Missing trait bound for + operator on T -> Option A
Quick Check:
Operators need trait bounds on generics [OK]
Hint: Add operator needs trait bound on generic type [OK]
Common Mistakes:
Ignoring trait bounds for operators
Assuming all types support + by default
Thinking references are always required
5. You want to write a generic function that returns the largest of two values. Which is the correct way to define it in Rust?
hard
A. fn largest(a: T, b: T) -> T { if a > b { a } else { b } }
B. fn largest<T>(a: T, b: T) -> T { if a > b { a } else { b } }
C. fn largest(a: T, b: T) -> T { if a > b { a } else { b } }
D. fn largest(a: T, b: T) -> T { if a > b { a } else { b } }
Solution
Step 1: Identify required trait for comparison
To compare two values with >, the type T must implement PartialOrd.
Step 2: Check trait bounds in options
fn largest(a: T, b: T) -> T { if a > b { a } else { b } } correctly uses T: PartialOrd. fn largest<T>(a: T, b: T) -> T { if a > b { a } else { b } } misses trait bound, C uses Copy which is unrelated to comparison, D uses Display which is for printing.
Final Answer:
fn largest<T: PartialOrd>(a: T, b: T) -> T { if a > b { a } else { b } } -> Option A
Quick Check:
Comparison needs PartialOrd trait bound [OK]
Hint: Use PartialOrd trait to compare generics [OK]
Common Mistakes:
Omitting PartialOrd trait bound
Using unrelated traits like Copy or Display
Assuming all types can be compared
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.