# While and Loop

Move offers two constructs for looping: `while` and `loop`.

## `while` loops

The `while` construct repeats the body (an expression of type unit) until the condition (an expression of type `bool`) evaluates to `false`.

Here is an example of simple `while` loop that computes the sum of the numbers from `1` to `n`:

``````fun sum(n: u64): u64 {
let sum = 0;
let i = 1;
while (i <= n) {
sum = sum + i;
i = i + 1
};

sum
}
``````

Infinite loops are allowed:

``````fun foo() {
while (true) { }
}
``````

### `break`

The `break` expression can be used to exit a loop before the condition evaluates to `false`. For example, this loop uses `break` to find the smallest factor of `n` that's greater than 1:

``````fun smallest_factor(n: u64): u64 {
// assuming the input is not 0 or 1
let i = 2;
while (i <= n) {
if (n % i == 0) break;
i = i + 1
};

i
}
``````

The `break` expression cannot be used outside of a loop.

### `continue`

The `continue` expression skips the rest of the loop and continues to the next iteration. This loop uses `continue` to compute the sum of `1, 2, ..., n`, except when the number is divisible by 10:

``````fun sum_intermediate(n: u64): u64 {
let sum = 0;
let i = 0;
while (i < n) {
i = i + 1;
if (i % 10 == 0) continue;
sum = sum + i;
};

sum
}
``````

The `continue` expression cannot be used outside of a loop.

### The type of `break` and `continue`

`break` and `continue`, much like `return` and `abort`, can have any type. The following examples illustrate where this flexible typing can be helpful:

``````fun pop_smallest_while_not_equal(
v1: vector<u64>,
v2: vector<u64>,
): vector<u64> {
let result = vector::empty();
while (!vector::is_empty(&v1) && !vector::is_empty(&v2)) {
let u1 = *vector::borrow(&v1, vector::length(&v1) - 1);
let u2 = *vector::borrow(&v2, vector::length(&v2) - 1);
let popped =
if (u1 < u2) vector::pop_back(&mut v1)
else if (u2 < u1) vector::pop_back(&mut v2)
else break; // Here, `break` has type `u64`
vector::push_back(&mut result, popped);
};

result
}
``````
``````fun pick(
indexes: vector<u64>,
let len1 = vector::length(v1);
let len2 = vector::length(v2);
let result = vector::empty();
while (!vector::is_empty(&indexes)) {
let index = vector::pop_back(&mut indexes);
let chosen_vector =
if (index < len1) v1
else if (index < len2) v2
else continue; // Here, `continue` has type `&vector<address>`
vector::push_back(&mut result, *vector::borrow(chosen_vector, index))
};

result
}
``````

## The `loop` expression

The `loop` expression repeats the loop body (an expression with type `()`) until it hits a `break`

Without a `break`, the loop will continue forever

``````fun foo() {
let i = 0;
loop { i = i + 1 }
}
``````

Here is an example that uses `loop` to write the `sum` function:

``````fun sum(n: u64): u64 {
let sum = 0;
let i = 0;
loop {
i = i + 1;
if (i > n) break;
sum = sum + i
};

sum
}
``````

As you might expect, `continue` can also be used inside a `loop`. Here is `sum_intermediate` from above rewritten using `loop` instead of `while`

``````fun sum_intermediate(n: u64): u64 {
let sum = 0;
let i = 0;
loop {
i = i + 1;
if (i % 10 == 0) continue;
if (i > n) break;
sum = sum + i
};

sum
}
``````

## The type of `while` and `loop`

Move loops are typed expressions. A `while` expression always has type `()`.

``````let () = while (i < 10) { i = i + 1 };
``````

If a `loop` contains a `break`, the expression has type unit `()`

``````(loop { if (i < 10) i = i + 1 else break }: ());
let () = loop { if (i < 10) i = i + 1 else break };
``````

If `loop` does not have a `break`, `loop` can have any type much like `return`, `abort`, `break`, and `continue`.

``````(loop (): u64);