A tour of Cuarzo

This page shows the language in a handful of examples. The language reference covers everything in detail.

Variables

Variables have an explicit type and an initializer. An f-string puts values into text:

int age = 25
f64 height = 1.68
str name = "Ana"
bool active = true
print(f"{name} is {age} and {height:1} m tall")   // Ana is 25 and 1.7 m tall

Functions and control flow

Functions use func, an optional result type before do, and end. Control flow has if, inclusive for ranges, while and match:

func add(int a, int b) int do
    return a + b
end

if add(2, 3) > 4 then
    print("big")
else
    print("small")
end

for i = 1 to 3 do
    print(i)
end

Arrays and maps

Arrays and maps grow as needed, and for ... in visits their contents:

int[] values = [3, 1, 2]
push(values, 4)

map[str, int] ages = {"ana": 31, "luis": 25}
ages["sofia"] = 40
for person, years in ages do
    print(person, years)
end
print(len(values), "luis" in ages)   // 4 true

Enums and match

Enum members can carry values, and match must handle every member:

enum Shape do
    CIRCLE(f64 radius)
    RECT(f64 width, f64 height)
end

func area(Shape shape) f64 do
    match shape do
        when CIRCLE(radius) then
            return 3.14159 * radius * radius
        when RECT(width, height) then
            return width * height
    end
end

Errors as values

Operations that can fail return a Result, or an Option when a value may be missing. ? passes an error on to the caller:

func add_text(str text) Result[int] do
    str[] parts = split(text, "+")
    if len(parts) != 2 then
        return Result.ERROR(f"expected a+b, got '{text}'")
    end
    return Result.OK(parse_int(trim(parts[0]))? + parse_int(trim(parts[1]))?)
end

match add_text("2 + 40") do
    when OK(sum) then
        print(sum)              // 42
    when ERROR(message) then
        eprint(message)
end

There are no exceptions: try, catch and throw are reserved words, but recoverable errors use Result.

Functions as values

Functions are values, short ones can be written as expressions with =>, and generic functions such as map, filter, reduce and sort work on any array:

int[] doubled = map(values, func(int n) => n * 2)
sort(doubled)
print(join(map(doubled, func(n) => to_str(n)), " "))   // 2 4 6 8

Structs

Structs are records shared by reference. Fields can have defaults, and values can be given by name:

struct Server do
    str host = "localhost"
    int port = 8080
    bool secure = false
end

Server api = Server("example.com", secure: true, port: 443)

Modules

Programs can be split into files with import "name", or with import "name" as lib to reach a module's names as lib.name. The standard library is imported the same way, as std/<name>:

import "std/json"

Memory

Programs manage memory with a garbage collector, so they can run indefinitely without leaking. Runtime faults such as an out-of-bounds index, a missing map key, a float that does not fit an integer, or deep recursion stop the program with a clear error and the calls that led to it.

Where to go next