Язык Odin
Давно подыскиваю для себя альтернативу языку C. Посмотрел на днях Rust, Nim, Zig, Hare и Odin. На первый взгляд, Odin — именно то что нужно. Единственный из всех не перегружен фичами (кроме Hare — но тот, напротив, слишком минималистичный даже для меня).
Может возникнуть вопрос: зачем мне вообще альтернатива C, если у меня уже есть Go? Go действительно прекрасен всем, кроме взаимодействия с C (которое мне иногда нужно). Кроме того, в нем есть сборщик мусора (который мне иногда не нужен).
Для меня Go — это замена Java. А хотелось бы еще замену C.
У Odin уникальный набор качеств:
- Простой язык без лишних прибамбасов.
- Ручное управление памятью с настраиваемыми аллокаторами.
- Продуманная стандартная библиотека.
- Лаконичный и спокойный синтаксис.
Тур по языку
Классический «привет, мир»:
package main
import "core:fmt"
main :: proc() {
fmt.println("Hellope!")
// Hellope!
}
Динамические массивы и сортировка:
package main
import "core:fmt"
import "core:slice"
main :: proc() {
list := [dynamic]int{11, 7, 42}
defer delete(list)
append(&list, 2, 54)
slice.sort(list[:])
fmt.println(list)
// [2, 7, 11, 42, 54]
}
Управление памятью ручное, так что выделенную память надо явно освобождать. Есть два встроенных аллокатора (heap и arena), но их можно менять прямо на лету:
// трассирующий аллокатор для отладки
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
// context - неявная переменная,
// доступна в любой области видимости
context.allocator = mem.tracking_allocator(&track)
// можно поменять аллокатор
// хоть на уровне отдельного выражения
list := make([]int, 6, context.allocator)
Структуры, процедуры и итерирование (здесь и дальше я не пишу package и прочую обвязку):
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
Нет ни функций, ни методов — только процедуры.
Указатели объявляются символом каретки перед названием переменной, а разыменовываются кареткой после названия:
val := "Hellope!"
ptr: ^string
ptr = &val
fmt.println(ptr^)
// Hellope!
Немного непривычно, но выглядит логично.
Ошибки — просто значения:
Error :: enum {
None,
Insufficient_Funds,
}
withdraw :: proc(balance, amount: int) -> (int, Error) {
if amount > balance {
return balance, .Insufficient_Funds
}
return balance - amount, .None
}
balance, err := withdraw(42, 1000)
if err != nil {
fmt.println(err)
}
// Insufficient_Funds
Есть сахарок для нелюбимого многими if err != nil return
:
balance := withdraw(42, 1000) or_return
Дженерики (параметрический полиморфизм):
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)
}
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
Здесь pair_to_str
принимает только значения типа Pair
или производных от него.
Как попробовать
Проще всего попробовать Odin в песочнице, которую я подготовил (именно в ней запускаются примеры из этой заметки).
Если предпочитаете локальную установку, на официальном сайте есть инструкция. Предоставляются бинарники для Windows, Linux и macOS — но, к сожалению, только amd64 (x86_64).
Если у вас arm64 Mac, можно использовать докер-образ (авторства Yeongju Kang с моими правками).
Специализация
Odin — язык общего назначения, но есть у него некоторая склонность к геймдеву и программированию визуальных эффектов. Наверно потому, что автор языка (Ginger Bill) — физик, который занимается как раз программированием визуальных эффектов.
Odin нативно предоставляет тип matrix
и операции над матрицами, а также функции, связанные с SIMD/SIMT-программированием (о котором я ничего не знаю, так что лучше почитайте официальную доку).
Насколько я могу судить, многие программисты используют Odin именно для разработки игр.
Статус языка
Odin пока не добрался до версии 1.0. Нет даже роадмапа до этой версии. К тому же, он не так популярен, как Zig или Nim (скорее ближе к Hare).
Но компания, в которой работает автор языка, активно использует Odin в продакшене, так что проверку реальностью он уже прошел.
Надеюсь, у языка большое будущее!
Подписывайтесь на твитер, чтобы не пропустить новые заметки 🚀