Examples

A sketch of what Zeno might look like. Nothing here is final

The whole of examples/tour.zeno, and what zeno run prints for it.

tour.zeno
# tour.zeno: a sketch of what Zeno might look like. Nothing here is final.
#
# Two rules:
#   1. Words over symbols. Keywords are whole words you can read aloud.
#   2. Punctuation has to earn its place. Braces mark blocks, and that's
#      about it: no semicolons, no colons after if/for, no brackets around conditions.


from math import sqrt


# --- Variables: say once whether a value can change ---

let name = "Zeno"                      # let: set once, never changes
var count = 3                          # var: can change later
count = count + 1                      # plain = updates an existing variable
let ports: list[int] = [80, 443, 8080] # write the type only when you want to

const PI = 3.14159                     # const: fixed when the program is built


# --- Functions ---

function greet(who: str, excited: bool = false) -> str {
    if excited {
        return f"Hello, {who}!"
    }
    return f"Hello, {who}."
}


# --- Classes: fields at the top, methods below ---

class Point {
    x: float
    y: float

    function distance_to(self, other: Point) -> float {
        return sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2)
    }
}

let origin = Point(0.0, 0.0)
let here = Point(x=3.0, y=4.0)


# --- Enums that carry data, and match to take them apart ---

enum Shape {
    Circle(radius: float)
    Rect(width: float, height: float)
}

function area(shape: Shape) -> float {
    match shape {
        case Circle(r) { return PI * r * r }
        case Rect(w, h) { return w * h }
    }
    # Forget a case and the compiler tells you, before the program ever runs.
}


# --- Errors: try / except / raise, but checked ---

function parse_port(text: str) -> int raises ValueError {
    let port = int(text)               # int() may raise ValueError; it passes up
    if not 1 <= port <= 65535 {        # comparisons chain, as in maths
        raise ValueError("port out of range")
    }
    return port
}

try {
    let port = parse_port("8080")
    print(f"listening on {port}")
} except ValueError as err {
    print(f"error: {err}")
}
# Under the hood a `try` remembers one place to jump back to. There are no
# unwinding tables as in C++, so it is cheap enough for a microcontroller.


# --- No surprise none ---

function find_user(id: int) -> str or none {
    if id == 1 {
        return "partha"
    }
    return none
}

let user = find_user(2)
if user is not none {
    print(user.upper())                # allowed only inside this check
}


# --- Loops ---

for shape in [Circle(1.0), Rect(2.0, 3.0)] {
    print(f"area = {area(shape):.2f}")
}

var tries = 0
while tries < 3 and ports[tries] != 8080 {
    tries += 1
}

let squares = [n * n for n in range(10) if n % 2 == 0]
print(greet(name, excited=true), count, squares, origin.distance_to(here))


# --- Functions are values, and units are types ---

function twice(f: function(int) -> int, x: int) -> int {
    return f(f(x))
}

function describe(delay: ms) -> str {    # only a quantity in ms is accepted
    return f"waiting {delay}"
}

print(twice(function(n) { return n * 3 }, 2), describe(500 ms))
zeno run examples/tour.zeno
listening on 8080
area = 3.14
area = 6.00
Hello, Zeno! 4 [0, 4, 16, 36, 64] 5.0
18 waiting 500 ms

See it on GitHub: examples/tour.zeno.