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

1. Indentation defines blocks

  • Status: Accepted
  • Date: 2026-09-02

Context

A block-structured language needs a way to mark where a block begins and ends. The mainstream options are delimiter pairs ({ }, begin/end, do/end) or significant indentation (Python, Haskell, F#, YAML).

Korrin's stated philosophy is minimal syntax and "one obvious way". Braces introduce a second, redundant signal: well-written code is already indented to show structure, and braces then have to agree with that indentation — when they disagree, the reader is misled and the compiler is not. Brace styles (same-line vs next-line, "cuddled" else) are also a perennial source of bikeshedding that a language can simply not have.

Decision

Indentation is the only thing that delimits a block. There are no { }, no begin/end, no end keyword.

  • A block is introduced by a header line ending in : followed by a newline.
  • The block's body is the run of following lines indented further than the header.
  • The body ends at the first line indented back to (or past, as a dedent) the header's level.
  • An empty body is written with the pass keyword on its own indented line.

The lexer turns this into explicit INDENT and DEDENT tokens; see 0007.

Consequences

  • No brace-style debate, no missing-brace bugs, less visual noise.
  • Copy-pasting code requires re-indenting — true of Python and broadly accepted.
  • The lexer is more complex: it carries an indentation stack and emits synthetic tokens. This complexity is contained in one place (see 0007).
  • Generated code and one-liners are not possible in the same way as a brace language. Korrin does not target code-generation-heavy use or shell one-liners, so this is acceptable.
  • Tooling that manipulates Korrin source must be indentation-aware.

Alternatives considered

  • Braces ({ }). Familiar, editor-friendly, but redundant with indentation and stylistically contentious. Rejected as "bolted on because other languages have it".
  • end keyword (Ruby/Lua style). Still redundant with indentation, adds vertical noise, and creates its own "stack of ends" problem in deep code.
  • Offside rule with optional braces (Haskell, Scala 3). Two ways to do one thing — directly against the design goal.