# Update list indices with List.set

URL: /docs/cookbook/indexed_update
Markdown: /docs/cookbook/indexed_update.md

> Reassign the new list returned by `List.set` while preserving earlier versions.

Generated by `cargo run -p agent_docs` from `compiler/examples/`. Edit the example files, then regenerate.

Reassign the new list returned by `List.set` while preserving earlier versions.

Collections have value semantics. `List.set(values, index, value)` returns a new
list; ignoring the result leaves `values` unchanged. The loop computes the length
once, handles empty input, then uses the half-open range `0..n`. Every read and
write is in bounds because replacement preserves length. An external index needs
both the nonnegative and upper-bound checks, as `replace_if_present` demonstrates.

The tests check changed values, the unchanged original list, empty and singleton
inputs, and external indices below zero, at the length and inside the list.
The harness also runs `main` and checks `[3, 0, 7, 0]`. No effects other than its
console output, permissions or slice/concat reconstruction are needed.

[Source project](https://github.com/icantcodefyi/sakuralang/tree/master/compiler/examples/indexed_update) · harness mode: `run + test`.

From the repository root, with this checkout's `sakura` on `PATH`:

```sh
cd compiler/examples/indexed_update
sakura check --json
sakura run
sakura test --json
```

### Manifest and permissions [#manifest-and-permissions]

```toml
[package]
name = "indexed_update"
version = "0.1.0"
edition = "2026"

[permissions]
```

### Source and tests [#source-and-tests]

`src/main.sakura` includes all required imports and tests.

```sakura test id=cookbook-indexed_update project=indexed_update
// milestone: M3
// mode: run
// spec: design §17.145

fn replace_negatives(values: List<Int>) -> List<Int> {
  var updated = values
  let n = List.len(updated)
  if n == 0 { return updated }
  for i in 0..n {
    let value = List.get(updated, i).expect("i is inside the half-open range")
    if value < 0 { updated = List.set(updated, i, 0) }
  }
  updated
}

pub fn main() -> Unit ! {Console} { Console.print("{replace_negatives([3, -2, 7, -1])}") }

test "updates preserve earlier versions" {
  let original = [3, -2, 7, -1]
  expect_eq(replace_negatives(original), [3, 0, 7, 0])
  expect_eq(original, [3, -2, 7, -1])
}

test "empty, singleton and unchanged inputs" {
  expect_eq(replace_negatives([]), [])
  expect_eq(replace_negatives([-1]), [0])
  expect_eq(replace_negatives([0, 4]), [0, 4])
}

fn replace_if_present(values: List<Int>, index: Int, value: Int) -> List<Int> {
  if index >= 0 && index < List.len(values) { List.set(values, index, value) } else { values }
}

test "external indices are checked before replacement" {
  expect_eq(replace_if_present([7], -1, 9), [7])
  expect_eq(replace_if_present([7], 1, 9), [7])
  expect_eq(replace_if_present([], 0, 9), [])
  expect_eq(replace_if_present([7], 0, 9), [9])
}
```

### Expected stdout [#expected-stdout]

```text
[3, 0, 7, 0]
```

### Compiler provenance and regeneration [#compiler-provenance-and-regeneration]

These eight projects teach supported Sakura APIs on the JavaScript backend. Each
project is exercised offline by `cargo test -p sakura_cli --test examples`;
HTTP and LLM exchanges are synthetic committed cassettes, with no network or API keys.
Use Node 26 for execution, including its built-in SQLite implementation.

The initial API baseline is compiler revision
[5cae349516c21714d90d36e87f1cfd6debe980c6](https://github.com/icantcodefyi/sakuralang/commit/5cae349516c21714d90d36e87f1cfd6debe980c6).
CI reruns these projects against the compiler in the same checkout. Build that
checkout's CLI and run `sakura --version` and `sakura prompt` before adapting a recipe;
pre-alpha APIs can change. An installed skill's frontmatter records its compiler
version and build revision. These teaching examples are separate from the agent
evaluation tasks.

The source of each page is its example's `recipe.md`, `sakura.toml`,
`src/main.sakura` and fixture files. Run `cargo run -p agent_docs` from `compiler/`
to regenerate the cookbook and skill reference. Edit those sources, not the rendered pages.
