features
[almost] everything is an expression
It is a goal for absolutely everything to be an expression. Right now most things are, like in Rust.
# if expressions
status := if score > 100 {
"absolute legend"
} else {
"noob"
}
# match expressions
value := match token {
.number(n) => n,
.ident(_) => 0,
}bindings
# immutable ::
never_change :: "hi there"
# mutable :=
sound := :loud
sound = :quiet
# fills :{}
Point :: struct { x: float, y: float }
Point :{
locate :: fn(self) {
print("I'm at ({self.x}, {self.y})")
}
}pipelines
# basic
call_to_action :: " let's do this " |> trim |> $ + "!!!" |> upper
# option/result aware
# short-circuits on none/error
nickname := find_user(id)
|> get_profile?
|> get_display_name?
or "anonymous"error handling
Errors are values, and recovery is explicit.
user := load_user(id) or {
return error("unknown user")
}leading literals
If there's only one literal argument, function parens may be omitted.
print "lol"
foo "bar"
sleep 1_000
log.group :processtrailing records
trailing functions
# if a function is the last argument of a call, it may be written after the parens.
retry(3) fn {
fetch(url)?
}
# if no named params are needed, the `fn` may be omitted
retry(3) {
fetch(url)?
}
# if the trailing function is the only argument, the parens may be omitted too
spawn {
do_work()
}implicit input
TODO: rename to something cooler?
$ is what gets passed to a function.
print_coord :: fn(x: int, y: int) {
print($.0, $.1)
}
This is especially useful inside pipelines.
# clojure-like threading
"hello" |> $ + " world"
"goodbye" |> wrap("[", $, "]")named returns
Bindings may be provided to return signatures, creating a mutable zeroed value.
divmod :: fn(a: int, b: int) out (int, int) {
out.0 = a / b
out.1 = a % b
return
}first-class testing
Tests are built into the language.
test "division" {
assert(div(8, 2) == 4, "should be the same")
}comfy tooling
CLI commands you're used to.
oi
oi repl
oi run .
oi exec "2 + 5"
# not yet implemented:
oi fmt
oi init
oi test
oi doc
oi build
oi watch
oi lsp