Try / Odin in Y minutes

Odin is a general-purpose programming language with distinct typing, designed for high performance, modern systems, and data-oriented programming. Some people refer to Odin as "better C".

Odin has a unique set of characteristics:

  • Simple language design without bells and whistles.
  • Manual memory management with custom allocators.
  • Well-thought standard library.
  • Concise and calm syntax.

✨ This guide needs some love

The guide is too brief. It would be great to take the official Odin overview and make it interactive. If you'd like to help — please contribute!

Some examples

A classic "hello world":

package main

import "core:fmt"

main :: proc() {
    fmt.println("Hellope!")
}
Hellope!

Dynamic arrays and sorting:

package main

import "core:fmt"
import "core:slice"

main :: proc() {
    list: [dynamic]int
    defer delete(list)

    append(&list, 11, 7, 42)
    append(&list, 2, 54)
    slice.sort(list[:])

    fmt.println(list)
}
[2, 7, 11, 42, 54]

Memory management in Odin is manual, so allocated memory must be explicitly freed. There are two built-in allocators (a heap allocator and a growing arena based allocator), but the language supports custom allocators:

// tracking allocator for debugging
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)

// context is an implicit variable
// available in every scope
context.allocator = mem.tracking_allocator(&track)

// we can use a custom allocator at any level,
// even at individual statements
list := make([]int, 6, context.allocator)

Structs, procedures and iteration (I'll skip the "package" stuff from now on):

Person :: struct {
    name: string,
    age: int,
}

person_to_str :: proc(p: Person) -> string {
    return fmt.tprintf("%v - %v", p.name, p.age)
}

people := []Person{
    Person{"Alice", 25},
    Person{"Bob", 24},
    Person{"Cindy", 26},
}

for p, idx in people {
    fmt.println(idx, person_to_str(p))
}
0 Alice - 25
1 Bob - 24
2 Cindy - 26

There are no functions or struct methods, only procedures.

Pointers are declared with a leading caret, and dereferenced with a trailing caret:

val := "Hellope!"

ptr: ^string
ptr = &val

fmt.println(ptr^)
Hellope!

A bit unusual, but logical.

Errors are just values:

Error :: enum {
    None,
    Insufficient_Funds,
}

withdraw :: proc(balance, amount: int) -> (int, Error) {
    if amount > balance {
        return balance, .Insufficient_Funds
    }
    return balance - amount, .None
}

try_withdraw :: proc(amount: int) -> Error {
    balance, err := withdraw(42, amount)
    if err != nil {
        return err
    }
    fmt.printf("✓ withdraw\n")
    return nil
}

main :: proc() {
    err := try_withdraw(1000)
    fmt.println(err)
}
Insufficient_Funds

There is also a shortcut for the dreaded if err != nil return:

balance := withdraw(42, amount) or_return
// no need for "if err != nil" anymore

Generics (aka parametric polymorphism):

Pair :: struct($T: typeid) {
    first: T,
    second: T
}

pair_to_str :: proc(p: $T/Pair) -> string {
    return fmt.tprintf("%v-%v", p.first, p.second)
}

main :: proc() {
    p1 := Pair(int){1, 2}
    p2 := Pair(string){"one", "two"}

    fmt.println(pair_to_str(p1))
    // 1-2

    fmt.println(pair_to_str(p2))
    // one-two
}
1-2
one-two

Here pair_to_str only allows types that are specializations of the Pair type.

Language overview

Specialization

Although Odin is a general-purpose language, it leans slightly towards game and visual effects programming. This is probably due to the fact that the language creator (Ginger Bill) is a physicist working in a visual effects company.

Odin supports a native matrix type and matrix operations, and has various SIMD/SIMT-related programming features (of which I don't know anything about, so better consult the doc for those).

As far as I can tell, a significant number of programmers using Odin are game developers.

Further reading

See the Odin documentation for a detailed overview, frequently asked questions, and language specification.

Anton Zhiyanov · original · CC-BY-SA-4.0 · 2023-07-31