composition[fn compose [f g] [fn [x] [f [g x]]]]
pipes[pipe data [filter valid?] [map transform] [sort-by :score]]
effects[effect Logger [log [msg : Str] : Unit]]
types[type Option [Some a] None]
pattern matching[match shape [Circle r] [* 3.14 r r] [Rect w h] [* w h]]
handlers[handle [greet] [Ask.prompt q] "World"]
ownership[let items #[1 2 3]] [let sorted [sort items]] ; items moved to sorted
macros[macro when [test & body] `[if ~test [do ~@body] []]]
Loon bird
loon

A functional language with invisible types, safe ownership, and algebraic effects.

Hindley-Milner inference eliminates type annotations. Ownership checking runs without lifetime syntax. Effects replace exceptions, async, and state.

curl -fsSL https://loonlang.com/install.sh | sh

Everything is an expression

No statements, no void returns. Every construct — if, match, let — produces a value. Square brackets replace parentheses for a clean, uniform syntax.

Guide: Basics →
[let greeting
  [if [> hour 17]
    "Good evening"
    "Hello"]]

[println greeting]  ; "Good evening"

Functions and pipes

First-class functions with implicit do blocks. Pipe chains thread data through transformations without nesting or temp variables.

Guide: Functions →
[fn process [items]
  [pipe items
    [filter [fn [x] [> [get x :score 0] 0.5]]]
    [map [fn [x] [update x :score [fn [s] [* s 2]]]]]
    [sort-by [fn [x] [get x :score 0]]]]]

Types without typing

Complete Hindley-Milner inference with let-polymorphism and row types for records. The compiler infers every type — you never write one.

Concepts: Invisible types →
; The compiler infers:
;   compose : (b -> c) -> (a -> b) -> (a -> c)
[fn compose [f g]
  [fn [x] [f [g x]]]]

[let inc-dbl [compose [fn [n] [+ n 1]]
                      [fn [n] [* n 2]]]]
[inc-dbl 5]  ; 11

Ownership without lifetimes

Values move by default. The compiler tracks ownership through dataflow analysis and catches use-after-move, double-free, and aliasing errors — no annotations needed.

Concepts: Ownership →
[let items #[1 2 3]]
[let sorted [sort items]]

; items has moved — using it here
; is a compile error:
; [println items]  ; error: moved

[println sorted]  ; #[1 2 3]

Algebraic effects

Declare effects as interfaces, perform them in functions, handle them at call sites. Effects replace exceptions, async/await, and mutable state with a single composable mechanism.

Concepts: Effects →
[effect Ask
  [prompt [q]]]

[fn greet []
  [let name [Ask.prompt "Name?"]]
  [str "Hello, " name "!"]]

; The caller decides how to handle it
[handle [greet]
  [Ask.prompt q] [resume "World"]]  ; "Hello, World!"

Pattern matching

Match on literals, ADT constructors, and wildcards. Destructure values directly in let bindings, function parameters, and match arms.

Guide: Pattern matching →
[type Shape
  [Circle Float]
  [Rect Float Float]]

[fn area [s]
  [match s
    [Circle r]  [* 3.14 r r]
    [Rect w h]  [* w h]]]

[area [Circle 5.0]]  ; 78.5