Docs/Language fundamentals

Strings & collections

Choose a container and work with text, sequences, and keyed data.

On this page

Use String for text, Array[T] for a growable sequence, and Map[T] for values keyed by strings. Use HashMap[K, V] when keys need another type.

Build and inspect text#

Valk
fn main() {
    let name = "Ada"
    let greeting = "Hello, %name"
    println(greeting.upper())
    println(greeting.contains("Ada"))
}

Strings support interpolation, concatenation with +, and methods such as starts_with, ends_with, and contains. String contents are read-only; operations such as upper() produce a result instead of changing the original text.

length and ordinary indexing work in bytes. For Unicode code points, use text.utf8.length, text.utf8.part(start, length), or each text.utf8.chars() as character. A code point is not always a complete visible character: accents and emoji sequences may contain several.

Grow an array#

Valk
fn main() {
    let scores = Array[int]{ 12, 8 }
    scores.append(20)
    println(scores.get(0) !? 0)
    println(scores.sum())
    each scores as score {
        println(score)
    }
}

get reports an error if the index is missing. Use a fallback when absence is expected, or handle that error explicitly. append adds to the end; clear removes all elements.

To transform a collection, use a callback. For example, scores.map[String](fn(score: int) String { return score.to(String) }) builds a new array of strings. Functions & closures explains callback types.

Look up a value by key#

Valk
fn main() {
    let stock = Map[int]{ "notebook" => 12, "pencil" => 30 }
    stock.set("eraser", 8)
    println(stock.get("notebook") !? 0)
    each stock as quantity, item {
        println("%item: %quantity")
    }
}

Use has to check whether a key exists, and remove to delete it. Removal can change iteration order, so do not use a map's iteration positions as persistent IDs.

For numeric keys, declare a type such as HashMap[uint, String].

Take part of a sequence#

Valk ranges use a start offset and a length. In values[1 .. 2], the second number means two elements, not an end index.

Valk
fn main() {
    let values = Array[int]{ 10, 20, 30, 40 }
    let copy = values[1 .. 2]
    copy[0] = 99
    println(values[1]) // 20: the original is unchanged
    println(copy[0])   // 99
}

Use &values[1 .. 2] to obtain a view of the same elements instead of a copy. A writable view changes the shared storage. See Memory & references before using views in APIs.

Choose fixed storage when the size is known#

A fixed array, [T x N], stores exactly N elements inline. A growable Array[T] manages its own storage. For a writable buffer with a chosen length, [u8]{ 0 x 1024 } allocates 1,024 zero bytes and returns an &mut [u8].

Valk
let point: [int x 2] = { 4, 7 }
let buffer = [u8]{ 0 x 1024 }

The buffer form is useful when reading files or streams.