7.1 Conditional Statements: if, else if, else

Conditional statements allow code execution to depend on whether a condition is true or false. Rust uses if, else if, and else, similar to C, but with important distinctions regarding type safety and usage as expressions.

7.1.1 Basic if Statements

The structure of a basic if statement is straightforward:

fn main() {
    let number = 5;
    // Parentheses around the condition are optional but allowed
    if number > 0 {
        println!("The number is positive.");
    }
    // Braces are always required, even for single statements
}

Key Differences from C:

  1. Strict Boolean Condition: The condition must evaluate to a bool type (true or false). Rust does not implicitly convert other types (like integers) to booleans.

    • C Example (Implicit Conversion):
      int number = 5;
      if (number) { // Compiles in C: non-zero integer treated as true
          printf("Number is non-zero.\n");
      }
      
    • Rust Equivalent (Error):
      fn main() {
      let number = 5;
      if number { // Compile-time error: expected `bool`, found integer
         println!("This won't compile");
      }
      }
      You must write an explicit comparison, like if number != 0.
  2. Braces Required: Curly braces {} are mandatory for the code block associated with if (and else/else if), even if it contains only a single statement. This prevents ambiguity common in C where optional braces can lead to errors (like the “dangling else” problem or incorrect multi-statement blocks).

7.1.2 Handling Multiple Conditions: else if and else

You can chain conditions using else if and provide a default fallback using else, just like in C:

fn main() {
    let number = 0;
    if number > 0 {
        println!("The number is positive.");
    } else if number < 0 {
        println!("The number is negative.");
    } else {
        println!("The number is zero.");
    }
}
  • Conditions are evaluated sequentially.
  • The block associated with the first true condition is executed.
  • If no if or else if condition is true, the else block (if present) is executed.

7.1.3 if as an Expression

Unlike C, where if is only a statement, Rust’s if can also be used as an expression, meaning it evaluates to a value. This is often used with let bindings and eliminates the need for a separate ternary operator (?:) like C has.

fn main() {
    let condition = true;
    let number = if condition {
        10 // Value if condition is true
    } else {
        20 // Value if condition is false
    }; // Semicolon for the `let` statement
    println!("The number is: {}", number); // Prints: The number is: 10
}

Important Requirement: When using if as an expression, all branches (the if block and any else if or else blocks) must evaluate to values of the same type. The compiler enforces this strictly.

fn main() {
let condition = false;
let value = if condition {
    5 // This is an integer (i32)
} else {
    "hello" // This is a string slice (&str) - Mismatched types!
}; // Error: `if` and `else` have incompatible types
}

If an if expression is used without an else block, and the condition is false, the expression implicitly evaluates to the “unit type” (). If the if block does return a value, this leads to a type mismatch unless the if block also returns ().

fn main() {
    let condition = false;
    // This `if` expression implicitly returns `()` if condition is false.
    let result = if condition {
        println!("Condition met"); // println! returns ()
    };
    // 'result' will have the type ()
    println!("Result is: {:?}", result); // Prints: Result is: ()
}