Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Edge Cases

Destructuring null or undefined

Destructuring a non-destructurable value throws a runtime TypeError — same as JavaScript:

(bind (object name) null)    ;; TypeError at runtime

rest Must Be Last

;; COMPILE ERROR
(bind (array (rest first) last) items)

rest collects remaining elements. It can only appear at the end of a pattern.

_ in Object vs Array Patterns

In array patterns, _ is a skip marker — it skips a position. In object patterns, _ is a regular binding name — it extracts a property called _. The distinction matters: (array _ second) skips the first element, but (object _) extracts a property named _.

Empty Patterns

(bind (object) x) compiles to const {} = x — valid JavaScript, but useless. The compiler allows it without error.

Destructured func Parameters

In surface func and fn, destructured params require type annotations on every field. A bare name is a compile error:

;; COMPILE ERROR: field 'name' missing type annotation (use :any to opt out)
(func f :args ((object name)) :body ...)

In multi-clause functions, two clauses that both destructure objects at the same position overlap — because dispatch can only check typeof, not the shape of the object’s properties.

Nested Destructuring Rules

Nested patterns in object destructuring must use alias to specify the property name:

;; COMPILE ERROR: must use alias
(func f :args ((object (object :string name))) :body ...)

;; OK: alias provides the property key
(func f :args ((object (alias :any c (object :string name)))) :body ...)

In array destructuring, nesting is positional — no alias needed.

Defaults and --strip-assertions

Default values survive --strip-assertions — they’re runtime semantics, not assertions. Only type checks are stripped:

// --strip-assertions: defaults preserved, type checks removed
function createUser({name, age = 0, role = "viewer"}) {
  return {name, age, role};
}

rest with default

rest collects all remaining elements. A default on rest is nonsensical and produces a compile error.