:title
4. Expressions and control flow

:content
An expression produces a value or performs an action. Capy evaluates listed expressions from left to right.

## Calculate a value

:example capy render
function RENDER()
{
	var price := 6
	var quantity := 2
	var total := price * quantity
	print(total, "\n")
}

:output
12

:content
`*` runs before `+` and `-`. Parentheses make the intended order explicit.

## Declare and assign locals

`:=` declares a local and infers its type. `=` replaces its value:

:example capy render
function RENDER()
{
	var count := 1
	count = count + 1
	print(count, "\n")
}

:content

A local exists until the end of its block. An inner block can declare a new local with the same name without changing the outer local.

## Conditions

Use `if` to select code:

:example capy render
function RENDER()
{
	var total := 12
	if total > 10
	{
		print("large\n")
	}
	else
	{
		print("small\n")
	}
}

:content

Capy evaluates each condition as `bool(condition)`. A condition can use any value with a `bool` constructor. A string has no `bool` constructor and cannot be a condition.

An `if` with `else` can also produce a value:

:example capy render
function RENDER()
{
	var total := 12
	var label := if total > 10
	{
		-> "large"
	}
	else
	{
		-> "small"
	}
	print(label, "\n")
}

:content

Each reachable branch that produces a value must produce the same type. A branch that returns or traps does not produce a value.

## Loops

A `while` loop repeats while its condition is true:

:example capy render
function RENDER()
{
	var index := 0
	while index < 3
	{
		print(index, "\n")
		index = index + 1
	}
}

:content

A `for` loop reads a half-open `s64` range, an array, or a `dval` map or list:

:example capy render
function RENDER()
{
	for number := 1..4
	{
		print(number, "\n")
	}
}

:content

The range is half-open. `1..4` contains `1`, `2`, and `3`. A range permits one loop value only.

Optional metadata follows the value:

:example capy render
function show(names : [string], profile : dval)
{
	for name, index := names
	{
		print(index, ": ", name, "\n")
	}
	for item, key := profile
	{
		print(key, ": ", item, "\n")
	}
}

function RENDER()
{
	show(["Ada"], role: "admin")
}

:content

An array index has type `s64`. A `dval` key has type `string`. `dval` list keys are decimal strings. Structs are not iterable. The old `=` and `in` forms are invalid.

Array and `dval` loops recheck the current count before each iteration. A loop can visit items added while it runs. Shrinkage cannot cause an invalid access. `dval` loop items are copies. An array loop retains its current managed item while the body runs.

Use `break` to leave the nearest loop. Use `continue` to start its next iteration.

## Blocks

A block yields a value when its final reachable item starts with `->`:

:example capy render
function RENDER()
{
	var total := { var subtotal := 10 -> subtotal + 2 }
	print(total, "\n")
}

:content

This makes `total` equal to `12`. A block can keep temporary locals close to the calculation that uses them.

:see-group
guides

:see
capy-03-values-and-types
capy-05-functions-and-closures
capy-07-collections-and-records
