rust-control-flujo-if-else

Flow Control in Rust with if, else and Expressions

  • 4 min

The flow control is the way to decide which instructions to execute and in what order.

So far, our programs have been a straight line: they run from top to bottom, instruction after instruction. Real software needs to make decisions: “if the user is logged in, show the dashboard; if not, show the login.”

For this we use flow control. If you come from C, Java, or JavaScript, the if and else syntax will feel very familiar, but in Rust there’s an important detail: it is an expression, not a statement.

Today, we’ll see how to write conditions and how to take advantage of this feature to write cleaner and more concise code.

Basic Syntax: if

The most basic structure is the if block. The syntax is very similar to other languages, with two small aesthetic differences:

  1. No parentheses () are needed around the condition.
  2. Curly braces {} are always mandatory (even if there’s only one line of code inside).
fn main() {
    let number = 7;

    if number < 10 {
        println!("The number is small");
    } else {
        println!("The number is large");
    }
}
Copied!

Multiple Conditions: else if

We can chain several conditions in the usual way.

let number = 6;

if number % 4 == 0 {
    println!("It's divisible by 4");
} else if number % 3 == 0 {
    println!("It's divisible by 3");
} else if number % 2 == 0 {
    println!("It's divisible by 2");
} else {
    println!("It's not divisible by 4, 3 or 2");
}
Copied!

If you have too many chained else if blocks, the code becomes hard to read. In Rust, when we have many branches, we usually prefer to use the match structure, which we’ll explore in depth later.

if as an Expression

In most languages, if is a statement. It’s an instruction that does something but doesn’t “return” anything.

In Rust, if is an expression. This means that when it runs, it returns a value. That is, it allows us to assign the result of an if directly to a variable.

Conditional Assignment

Imagine you want to assign a value to a variable depending on a condition. In other languages, you would do this:

// JavaScript style (imperative)
let condicion = true;
let x;
if (condicion) {
    x = 5;
} else {
    x = 6;
}
Copied!

In Rust, we can do it much more elegantly:

// Rust style (expression)
fn main() {
    let condition = true;

    let x = if condition { 5 } else { 6 };

    println!("The value of x is: {}", x);
}
Copied!

Let’s break down what just happened:

  1. We declare let x =.
  2. We evaluate the if block.
  3. If it’s true, the block returns 5.
  4. If it’s false, the block returns 6.
  5. That result is assigned to x.

Notice that the numbers 5 and 6 inside the curly braces do not have a semicolon. This is because we want to return them (remember: in Rust, the last line without ; is the return value).

Where is the ternary operator? Many ask about the ternary operator condition ? value1 : value2 from C/JS.

In Rust, it doesn’t exist because it’s not needed. if else already works like a ternary operator, but more readable.

Type Coherence

Since we are assigning the result to a variable (x), Rust needs to know what type x is. Therefore, all branches of the if must return the same data type.

The following code does not compile:

let condition = true;

// ❌ Error: `if` and `else` have incompatible types
let number = if condition {
    5       // This is an integer (i32)
} else {
    "six"   // This is a string (&str)
};
Copied!

Rust will give us the error E0308. It cannot create a variable that is sometimes a number and sometimes text (for that we would need an enum, which we’ll cover later).