# Conditions and loops

> Write branching expressions, loops, early exits, and case decisions.

Canonical: https://alice-lang.org/documentation/language/control-flow/

[Documentation index](https://alice-lang.org/documentation/llms.txt) · [Complete book](https://alice-lang.org/llms-full.txt)

## If, elsif, and else

```alice
def describe(n : Int32) : String
  if n < 0
    "negative"
  elsif n == 0
    "zero"
  else
    "positive"
  end
end
for n in -1..1
  puts describe(n)
end
```

Expected output:

```text
negative
zero
positive
```

[Edit and run in the Alice playground](https://playground.alice-lang.org/#code=u.ZGVmIGRlc2NyaWJlKG4gOiBJbnQzMikgOiBTdHJpbmcKICBpZiBuIDwgMAogICAgIm5lZ2F0aXZlIgogIGVsc2lmIG4gPT0gMAogICAgInplcm8iCiAgZWxzZQogICAgInBvc2l0aXZlIgogIGVuZAplbmQKZm9yIG4gaW4gLTEuLjEKICBwdXRzIGRlc2NyaWJlKG4pCmVuZA)

The first true branch is selected. `if` can be a statement or an expression. When used as a value, make the branches produce compatible results:

```alice
size = 12
label = if size > 10
  "large"
else
  "small"
end
puts label
```

Use `unless condition` for a negated condition, or a postfix condition for a short guarded statement:

```alice
puts "ready" if size > 0
puts "empty" unless size > 0
```

For a small value choice, `condition ? a : b` is also available.

## Case decisions

`case subject` with `when` compares against alternatives. A `when` can have several values. `then` puts a short branch on the same line. A case can produce a result just like `if`.

```alice
number = 2
label = case number
when 1, 2 then "small"
when 3 then "three"
else "other"
end
puts label
```

For destructuring records, arrays, hashes, and enum variants, read [pattern matching](https://alice-lang.org/documentation/language/pattern-matching.md). Enum cases must be exhaustive or provide an `else`.

## While and until

`while` repeats while a condition is true. `until` repeats until it becomes true.

```alice
n = 0
while n < 3
  puts n
  n += 1
end
```

Update the condition's state deliberately. An accidental infinite loop behaves like any other program loop; use small bounds when experimenting in the browser.

## For and iterator blocks

```alice
for n in 1..3
  puts n
end

for key, value in {"tea" => 2, "cake" => 1}
  puts "#{key}: #{value}"
end

3.times { |i| puts i }
```

`for` iterates a range or collection. `times` starts its block index at zero. Use `0...array.size` when you need valid indices. Iterator methods such as `each`, `map`, and `select` are described in [collections](https://alice-lang.org/documentation/library/collections.md).

## Break, next, and return

`break` leaves a loop, `next` skips to its next iteration, and `return` leaves a method. A guard clause can combine `return` with postfix `if`.

Order-dependent loops and loops with effects are not automatically parallelized just because their bounds are large. Read [performance](https://alice-lang.org/documentation/guides/performance.md) before relying on a particular optimization.

## Continue reading

- Previous: [Operators and expressions](https://alice-lang.org/documentation/language/operators.md)
- Next: [Methods and calls](https://alice-lang.org/documentation/language/methods.md)
