DEV Community

Cover image for [Rust Guide] 3.5. Control Flow - If Else
SomeB1oody
SomeB1oody

Posted on

[Rust Guide] 3.5. Control Flow - If Else

3.5.0. Before We Begin

Welcome to Chapter 3 of this Rust self-study series. It has 6 sections:

  • Variables and Mutability
  • Data Types: Scalar Types
  • Data Types: Compound Types
  • Functions and Comments
  • Control Flow: if else (this article)
  • Control Flow: Loops

Through the guessing game in Chapter 2 (beginners who have not read it are strongly encouraged to take a look), you should now have learned the basic Rust syntax. In Chapter 3, we will go one level deeper and learn the general programming concepts in Rust.

If you find this helpful, please like, bookmark, and follow. To keep learning along, follow this series.

3.5.1. The Basics of if Expressions

  • An if expression allows different code branches to run depending on a condition.
    • The condition must be a boolean type. This is different from Ruby, JS, and C++, which convert non-boolean values after if into boolean values.
    • The condition can be a literal, an expression, or a variable.
  • In an if expression, the code associated with the condition is called a branch (we already mentioned this concept when discussing match).
  • Optionally, you can add an else expression afterward.
fn main(){
    let machine = 6657;

    if machine < 114514 {
        println!("condition is true");
    } else {
        println!("condition is false");
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the value of machine is less than 114514, so the program executes the line println!("condition is true");. If you change the value of machine so that it is no longer less than 114514, then the program will execute the code block after else.

3.5.2. Handling Multiple Conditions with else if

If you need to evaluate multiple conditions and do not want to keep nesting under else, then else if is a very good choice.

fn main(){
    let number = 6;
    if number % 4 == 0 {
        println!("Number is divisible by 4");
    } else if number % 3 == 0 {
        println!("Number is divisible by 3");
    } else if number % 2 == 0 {
        println!("Number is divisible by 2");
    } else {
        println!("Number is not divisible by 4, 3, or 2");
    }
}
Enter fullscreen mode Exit fullscreen mode

Since 6 is divisible by both 3 and 2, both else if number % 3 == 0 and else if number % 2 == 0 are true. Because if, else if, and else are evaluated in order from top to bottom, whichever branch appears first is the one that runs. In this example, else if number % 3 == 0 appears first, so the program executes println!("Number is divisible by 3");, and the code block under else if number % 2 == 0 is not executed.

If your program uses more than one else if, it is usually better to refactor it with match.

For example, the code above can be refactored like this (one possible solution):

fn main() {
    let number = 6;

    match number {
        n if n % 4 == 0 => println!("Number is divisible by 4"),
        n if n % 3 == 0 => println!("Number is divisible by 3"),
        n if n % 2 == 0 => println!("Number is divisible by 2"),
        _ => println!("Number is not divisible by 4, 3, or 2"),
    }
}
Enter fullscreen mode Exit fullscreen mode

Obviously, the match version is more intuitive.

3.5.3. Using if in a let Statement

if is an expression in Rust, so you can put it on the right-hand side of the equals sign in a let statement.

fn main(){
    let condition = true;
    let number = if condition { 5 } else { 6 };
    println!("The value of number is: {}", number);
}
Enter fullscreen mode Exit fullscreen mode

In this example, because condition is true, 5 is assigned to number, and the final output is The value of number is: 5. If condition is false, then the value after else, 6, is assigned to number.

This syntax is very similar to Python, but there is a fundamental difference between the two:

  • Rust:

    • In Rust, if-else is an expression and can directly return a value. In other words, the if construct itself can participate in the evaluation of other expressions.
    • In Rust, almost any code block can be an expression, so a {} block can also return a value.
  • Python:

    • In Python, if-else is a specific ternary-like form designed for single-line conditional expressions.
    • Python's ordinary if-else statement is part of control flow; it does not return a value and cannot be embedded inside other expressions.
fn main(){
    let condition = true;
    let number = if condition { 5 } else { "6" };
    println!("The value of number is: {}", number);
}
Enter fullscreen mode Exit fullscreen mode

This example will fail to compile with the error: if` and `else` have incompatible types. This means that if and else return incompatible types. Because Rust is a statically typed, strongly typed language, it must know a variable's type at compile time so that the variable can be used elsewhere. In this example, the return value of the if branch is i32, while the return value of the else branch is a string type. The compiler cannot determine at compile time whether the type of number should be i32 or a string, so it reports an error.

In one sentence: the branches of an if-else expression must return values of the same type.

Top comments (0)