:title
7. Arrays and structs

:content
Use an array for an ordered collection of one type. Use a struct when fields need names.

## Arrays

:example capy render
function RENDER()
{
	var names := ["Ada", "Grace"]
	print(names[0], "\n")
}

:output
Ada

:content
Array indexes start at zero. An invalid index traps.

Declare the item type when an array starts empty:

:example capy render
function RENDER()
{
	var names : [string] = []
	names.push("Ada")
	print(names[0], "\n")
}

:content

`push`, `pop`, `insert`, `remove`, `clear`, `reserve`, and `resize` change an array.

## Array values

An array is an object. A variable holds a reference to it, and two variables can refer to the same array:

:example capy render
function append_three(values : [s64])
{
	values.push(3)
}

function RENDER()
{
	var first := [1, 2]
	var second := first
	append_three(second)
	print(first[2], " ", second[2], "\n")
}

:content

An array is an object. `var b := a`, a parameter, a return value, or a capture gives the same array another name, and a change through one name shows through all. A parameter name cannot be pointed elsewhere, so `values = [3]` inside a function is a compile error; `values[0] = 3` is fine. Growing an array keeps it the same object.

A `for` loop reads array items in order:

:example capy render
function RENDER()
{
	var names := ["Ada", "Grace"]
	for name, index := names
	{
		print(index, ": ", name, "\n")
	}
}

:content

The optional index follows the value and has type `s64`. The loop rechecks the current array length. It safely stops after shrinkage and can visit appended items. The loop retains each current managed item while the body runs.

The loop item is a value, not an assignable array position. Use an index to replace an item.

## Structs

A struct defines a named fixed layout:

:example capy render
struct Point
{
	x : s32
	y : s32
}

function RENDER()
{
	var point := Point(3, 4)
	print(point.x, " ", point.y, "\n")
}

:content

The generated constructor takes fields in declaration order. A struct instance is an object: assignment, parameters, return values, and captures give it another name rather than a copy. Struct fields are assignable:

:example capy render
struct Point
{
	x : s32
	y : s32
}

function move_right(point : Point)
{
	point.x = point.x + 1
}

function RENDER()
{
	var point := Point(3, 4)
	move_right(point)
	print(point.x, "\n")
}

:content

The field mutation affects the caller. The parameter binding itself remains immutable.

A receiver-first function can use method syntax:

:example capy render
struct Point
{
	x : s32
	y : s32
}

function total(point : Point) s32
{
	-> point.x + point.y
}

function RENDER()
{
	var point := Point(3, 4)
	print(point.total(), "\n")
}

:content

This is the same call as `total(point)`.

## Inspect a struct

Use `value::size` to get the number of declared fields. Use `value::items` when code must inspect fields by name.

:example capy render
struct Build
{
	id : s64
	status : string
}

function RENDER()
{
	var build := Build(s64(9007199254740993), "ready")
	var fields := build::items
	var key := "status"
	print(build::type_name, " ", build::size, "\n")
	print(fields[key].type_name, " ", string(fields[key].value), "\n")
}

:output
Build 2
string ready

:content

`value::items` returns a `dval` map keyed by field name. Each field entry has `value` and `type_name` keys. Use `fields.id.value` for a fixed field name. Use `fields[key]["value"]` for a dynamic field name.

The reflected field value is a `dval`. Convert it to the static type before using it in typed code. The struct reference page defines nested values, copying, and callable fields.

## Choose the right shape

Use an array when every item has one static type. Use a struct for application data with a stable shape. Use a `dval` map or list for decoded input and data that crosses a Bearer boundary.

:see-group
guides

:see
capy-03-values-and-types
capy-05-functions-and-closures
capy-08-dynamic-values
type/struct
get_type_name
length
set
