A 10-Minute Tour of Loon

Everything you need to know to start writing Loon.

1. Hello, World

Loon uses square brackets for everything. A function call is just a list: [function arg1 arg2].

[fn main []
  [println "Hello, world!"]]

2. Bindings & Types

Use let to bind values. Types are fully inferred — you never need to write them.

[let name "Loon"]
[let age 1]
[let pi 3.14159]
[let active true]
[let items #[1 2 3]]

3. Functions

Functions are defined with fn. Multi-arity is supported natively.

[fn square [x] [* x x]]

[fn greet
  ([name] "Hello, {name}!")
  ([first last] "Hello, {first} {last}!")]

4. The Pipe Operator

Thread data through a pipeline. pipe passes the result as the last argument.

[pipe [range 1 20]
  [filter [fn [n] [= 0 [% n 2]]]]
  [map [fn [n] [* n n]]]
  [take 5]
  [each println]]

5. Pattern Matching

Match on values, ADT constructors, and more.

[type Shape
  [Circle f64]
  [Rect f64 f64]
  Point]

[fn area [shape]
  [match shape
    [Circle r] [* 3.14159 [* r r]]
    [Rect w h] [* w h]
    Point 0.0]]

6. Algebraic Effects

Effects replace exceptions, async/await, and state.

[effect Console
  [fn log [msg]]]

[fn greet [name]
  [Console.log "Hello, {name}"]]

[handle [greet "world"]
  [Console.log msg] [println msg]]

7. Modules

Organize code into modules. Use pub to export, use to import.

; math.loon
[pub fn add [a b] [+ a b]]

; main.loon
[use math]
[println [math.add 1 2]]

8. Collections & Destructuring

Rich collection types with destructuring in function params and let bindings.

[let #[a b c] #[1 2 3]]
[let {name age} {:name "Loon" :age 1}]

[fn process-pair [[x y]]
  [+ x y]]