Kiki

Shortest Hello World to Literate Programming

Shortest hello world

In almost every programming language, greeting the world requires some ceremonies. One early example from 1974 Bell Laboratories shows how to do it in C, which requires printf and main:

main( ) { printf("hello, world"); }

In a document-oriented programming language (like Tex, Typst, Scribble, Literate Haskell), the hello world program is literally just 12 characters:

hello, world

This is arguably the world's shortest hello world program.

Saying it is a program, means that it can compute, unlike a Markdown or TXT file. For example:

hello, #upper("world") // Typst hello, @(string-upcase "world") // Scribble hello, \(string.upper "world") // Kiki

Then the program is evaluated to "hello, WORLD".

Invert code and block comment

Modern programming languages often adopt a markup format in their block comment systems. For example, Rust supports:

These are quite useful when reading documentation, allowing non-linear exploration.

What if we take a step further and make comments first class?

Let's see a piece of Kiki program:

`fib` returns n-th Fibonacci number. E.g., 10th Fibonacci number is \(fib 10). > fib = fn 0 -> 1 fn 1 -> 1 fn n -> fib (n - 1) + fib (n - 2)

Note a few interesting things:

  1. The program starts with prose (like block comments) instead of code. A leading > enters code mode.
  2. Backtick like fib in prose refer to local symbols or imported symbols (such as string.trim). In the IDE and documentation, clicking a symbol jumps to its definition.
  3. Inline computation is written with \(..).

The core idea is that both prose and code are parsed and type-checked by the same compiler, rather than two separate systems.

The main cost of inverting code and comments is that, now code requires additional syntax and indentation.

However, the benefits are significant too:

  1. We have a home for docs. Design docs and module level comments all use the same markup syntax.
  2. Docs can keep sync with code. Refactor can rename a symbol across all code and prose references.
  3. Context is always nearby. Nowadays AI is pretty good at locating context, though easily available context still helps.

Literate programming

Donald Knuth introduced Literate Programming in 1984 when he built the Tex typesetting system. He created a system called WEB, which embeds Pascal code in the Tex prose. The whole Tex implementation is a 25101 lines of tex.web file. It is like a book or a design doc, started with high level designs, then progressively introduce algorithms used and code pieces. The file can be extracted into Pascal program and Tex doc. Tex being impelemented by Tex+Pascal is an interesting bootstraping approach.

a
asdfa

Living examples over comment rot

When Donald Knuth introduced Literate Programming in 1984, he formulated its core philosophy:

The main idea is to regard a program as a communication to human beings rather than as a set of instructions to a computer.

In traditional software development, comments and code live in separate worlds:

Because the compiler ignores comments, they inevitably rot. We have all encountered docstrings with outdated return values, broken code snippets, or explanations for arguments removed three refactors ago.

When prose is first-class, \(fib 10) shares the same scope and runtime as the fib definition. If fib changes or breaks, the prose immediately updates or raises a compile error. The example is not a static snapshot—it is a living evaluation. The explanation cannot drift from the execution.

The friction of the past

If the idea is so compelling, why didn't literate programming become the default way we write all software?

Historically, the friction came from the toolchain:

This split created friction: compiler errors pointed to generated files rather than the original document, and standard debuggers and IDEs struggled to keep up.

In a modern expression-oriented language, those barriers disappear. Functions, expressions, and prose can coexist in a single unified AST. There is no preprocessor or code extraction pass—the document is the source, and the source is the document.

First-class explanation in the tooling

In most editors, comments are styled in a muted gray color—a subtle cue that the editor and compiler do not care about what is written there.

When prose is part of the language grammar rather than discarded in the lexer:

Code as an essay vs. code as plumbing

The goal of a document-first style is not to force every five-line utility function or configuration file into an essay. Much of software engineering is plumbing where concise, traditional code files remain effective.

Rather, literate programming shines where human intent matters most: algorithms, tutorials, technical design specifications, domain models, and data analyses. In these domains, understanding *why* a piece of code exists is just as crucial as *what* instructions the CPU executes.