Data flows left to right.
A pipe passes the value on its left as the first argument on its right. A block with x is a lambda.
A pipe passes the value on its left as the first argument on its right. A block with x is a lambda.
let result = [5, 2, 8, 1]
| Array.filter({ x > 2 })
| Array.map({ x * 10 })
| Array.sort()
println(result)[50, 80]A function that can fail returns a Result. try hands an error up to the caller. Nothing is thrown.
func load(path: string): Result[Json.Value, Error] {
let text = try File.read(path)
Json.parse(text)
}
let config = load("config.json")
if config is Err { println(config.error.message) }open config.json: no such file or directoryGoroutines are cheap, and any function can start one. Parallel.map runs a function over a list on goroutines, at most limit at once, and returns when all of them are done.
func slowSquare(n: int, ctx: Context): int {
Time.sleep(100ms, ctx)
n * n
}
let squares = Parallel.map([1, 2, 3, 4], slowSquare, limit: 3)
println(squares)[1, 4, 9, 16]Markup is a value of type Html, checked like any other expression. Text interpolated into it is escaped, so a page is safe by default.
type Post = { title: string, url: string }
func link(post: Post): Html {
<a href={post.url}>{post.title}</a>
}
let post = Post{ title: "Hello <world>", url: "/hello" }
println(<p>{link(post)}</p>)<p><a href="/hello">Hello <world></a></p>The language server brings completion, hover, go to definition, rename, and diagnostics to VS Code, IntelliJ, and Neovim. The debugger sets breakpoints and shows values, and ant fmt formats on save.