Turning questions into booleans
An if statement needs a bool condition. Most of the time that boolean comes from comparing two values. A comparison operator looks at the values on its left and right and produces true or false.
| Operator | Meaning | Example |
|---|---|---|
== | equal to | x == 5, x == y |
!= | not equal to | x != 3, x != y |
> | greater than | x > 5, x > y |
< | less than | x < 8, x < y |
>= | greater than or equal to | x >= 4, x >= y |
<= | less than or equal to | x <= 3, x <= y |
Each expression is a value of type bool that you can store, print or use as a condition:
println!("{}", 10 == 10);
println!("{}", 3 < 2);
println!("{}", 15 >= 15);
println!("{}", 17 != 12);
true
false
true
true
The edge cases are the ones to watch: 15 >= 15 is true because "or equal" counts, while 15 > 15 would be false.
Using them with variables
Comparisons are usually made between variables and values:
let a = 10;
let b = 15;
if a == b {
println!("a is equal to b");
}
if a < b {
println!("a is less than b");
}
The first condition, 10 == 15, is false, so its block is skipped. The second, 10 < 15, is true. The program prints a is less than b.
Rust's strictness
Both sides must have the same type
Rust refuses to compare values of different types. An i32 and an i64 can't be compared directly, and neither can an integer and a float:
let a: i32 = 10;
let b: i64 = 10;
println!("{}", a == b);
error[E0308]: mismatched types
Convert one side first, for example i64::from(a) == b, or for floats v as f64 == f. Literals adapt on their own: in x > 5 the 5 becomes the same integer type as x. But an integer variable can't be compared with a float literal such as 5.0.
No chaining
In maths you can write 1 < x < 5. In Rust that is a compile error ("comparison operators cannot be chained"). Combine two comparisons with && (and) instead:
let x = 3;
println!("{}", x >= 1 && x <= 5);
true
Other types
Comparisons aren't limited to numbers. Characters and strings compare too, and strings are ordered by their bytes (for ASCII text, by character code):
'a' < 'b'istrue."apple" < "banana"istrue."Zebra" < "apple"istrue, because every uppercase letter has a smaller code than any lowercase one.String::from("hi") == "hi"istrue, and so is the reverse,"hi" == String::from("hi").
Combining comparisons
Real conditions often need more than one test. Rust has three logical operators for combining booleans: && is true when both sides are true, || is true when at least one side is, and ! flips a boolean. Each comparison is evaluated first and the logical operator joins the results:
let x = 3;
println!("{}", x == 3 || x == 4);
println!("{}", !(x > 10));
true
true
The operators && and || stop early: when the left side already decides the answer, the right side is not evaluated. You will use this later to guard a risky check behind a safe one.
= is not ==
A single = assigns a value to a variable, while == compares two values. Writing if x = 5 does not compile in Rust, since an assignment isn't a bool. The compiler suggests that you may have meant to compare.
The exercise
The starting code declares let grade = 8;. A grade below 5 means the test was failed. The lesson walks through the decision in three steps:
- Write an
ifchecking thatgradeis less than5, with the<operator. No parentheses are needed, but the braces are. - Inside it, print
"Failed the test"withprintln!. - Add an
elsethat prints"Passed the test", because every grade of 5 or more is a pass.
let grade = 8;
if grade < 5 {
println!("Failed the test");
} else {
println!("Passed the test");
}
With a grade of 8, 8 < 5 is false, so the program prints Passed the test. The strict < matters: a grade of exactly 5 is not less than 5, so it passes. Using <= would wrongly fail it.
Key takeaways
- Comparison operators produce a
bool:==,!=,>,<,>=,<=. - Both sides must have the same type, and comparisons can't be chained.
- Use
&&to combine two comparisons. - Check the boundary value when choosing between
<and<=.
