
func findUser(id: Int64) -> Optional[User] { let user = match users.get(id).tryExtract() { .Continue(v) => v, .Break(r) => return fromResidual(r) }; if user.age.compare(18) == .Less { return Optional.None }; user } func greet(id: Int64) -> String { let user = findUser(id).coalesce(default: { User(name: "guest", age: 0) }); var s = DefaultStringInterpolation(literalCapacity: 7, interpolationCount: 1); s.appendLiteral("Hello, "); user.name.format(into: s); s.appendLiteral("!"); String(interpolation: s) } func main() { var it = Array(arrayLiteral: LiteralSlice("Alice", "Bob", "Carol")).iter(); loop { match it.next() { .Some(name) => print(name), .None => break } } }
func findUser(id: Int64) -> User? { let user = try users.get(id); if user.age < 18 { return null }; user } func greet(id: Int64) -> String { let user = findUser(id) ?? User(name: "guest", age: 0); "Hello, \(user.name)!" } func main() { for name in ["Alice", "Bob", "Carol"] { print(name) } }
This looks like any modern language. Clean syntax, readable defaults, nothing unusual.
But none of it is special-cased.
Every shortcut is a protocol you can see, touch, and replace.
T?→try→<→null→??→\(...)→for...in→[...]→The standard library uses these protocols to implement Optional, Result, Array, and String. Conform your own types and they get the same syntax — because it's the same machinery.
struct Countdown: Iterator { type Item = Int64 var current: Int64; mutating func next() -> Int64? { if self.current <= 0 { return null }; self.current -= 1; self.current + 1 } } for n in Countdown(current: 5) { print(n) }
import perch.app.(App) import perch.request.(Request) import perch.response.(Response) import perch.middleware.(Logger) import http.content.(Text, JsonBody) struct Ctx: Cloneable { func clone() -> Ctx { Ctx() } } var app = App(Ctx()); app.use(Logger()); app.route(get: "/hello/:name", { (req: Request, ctx: Ctx) in let name = req.param("name") ?? "world"; Response.ok(Text("Hello, \(name)!")) }); app.listen(8080);
struct Money { @ensures(value >= 0) var value: Float64; } struct Account { var balance: Money; mutating func withdraw(amount: Money) -> Money { self.balance -= amount.value; // error: self.balance must stay above 0 return amount; } }
Install the toolchain and run your first Kestrel program
$ curl -fsSL https://kestrel-lang.com/install | shInstalls Jessup, the Kestrel version manager, the latest stable toolchain, the VS Code extension, and the Claude Code / Codex plugin. View the script.