A family of grid languages, not one language
Funge-98 is best understood as a specification for a family of programming languages whose programs live on a grid. A pointer moves across that grid, reads one cell at a time, and obeys whatever instruction it finds. The original Befunge, usually called Befunge-93, was a single two-dimensional language. Funge-98 takes the same core idea and states it in a more general, more carefully defined way. The “98” in the name points to the late 1990s, when this generalization was written down.
This site is an independent explainer. It is not the official home of any language or standard, and the details below stay at the level of well-known general facts.
The core idea carried over from Befunge
Everything that makes a Funge program feel unusual comes from Befunge. Code is not read top to bottom. Instead, an instruction pointer has a position and a direction, and the instructions on the grid can change that direction. Data lives on a stack, and the program can also read and write cells of the grid itself, so code and data share the same space.
If those ideas are new, the Befunge language is the place to build them up first. Funge-98 assumes you are comfortable with the pointer, the stack and the idea that a program is a picture of its own control flow. Most simple Befunge-93 programs keep working under a Funge-98 interpreter, which was one of the stated goals: widen the language without throwing away what already existed.
What Funge-98 sets out to do
Reading the specification as a whole, a few goals stand out.
- Remove arbitrary limits. Befunge-93 fixed its playfield at a small rectangle. Funge-98 describes a space that is unbounded in principle, with real implementations limited only by memory.
- Define behavior precisely. Several corners that were vague or implementation-dependent in the older language are given explicit rules, such as what an unknown instruction does and how the pointer wraps.
- Allow more dimensions. The same rules are written for one, two and three dimensions, giving Unefunge, Befunge and Trefunge in the Funge-98 sense.
- Make the language extensible. A mechanism called fingerprints lets a program load extra sets of instructions by name.
- Add richer features. Concurrency, a stack of stacks, file access, system queries and more flexible jumping are all part of the picture.
These goals do pull against each other a little. A bigger specification is harder to implement fully, which is why Funge-98 interpreters vary in how much they support. That tradeoff is a recurring theme in language design generally.
Main differences from Befunge-93
A full comparison belongs in its own article, but a quick overview helps. The playfield is no longer a fixed 80 by 25 rectangle. The pointer can move in directions beyond the four compass points. New instructions appear for jumping over cells, repeating an instruction, splitting into several pointers, reflecting the pointer, and turning left or right. Letters A to Z are reserved for extensions, and unknown instructions behave in a defined way rather than being left unspecified.
Some changes touch things you might not notice at first. Space handling is more careful, and the stack model is richer, since the single stack becomes a stack of stacks. The Funge-98 features covered later in this site’s deeper articles each take one of these changes and explore it in detail.
A first taste of the new instructions
Here is a tiny Funge-98 style program:
1.;this text is skipped;2.@
The pointer moves right, pushes 1, and prints it with the dot instruction, which outputs a number followed by a space. It then meets a semicolon. In Funge-98, a semicolon starts a skipped region, and the pointer passes over everything until the next semicolon without executing it. After that it pushes 2, prints it, and stops at the at sign. The output is “1 2 “ with a trailing space. In Befunge-93 the semicolon has no such meaning, so this idea of cheap inline comments is genuinely new in the later language.
Dimensions and the pointer
Because Funge-98 is defined for several dimensions, the pointer’s direction is really a vector with one component per dimension. In two dimensions the familiar four directions are just the vectors that point up, down, left or right. Once you accept that, an instruction that sets an arbitrary vector, such as one that moves two cells at a time, follows naturally. This is the territory of delta vectors, and it is a good example of how a generalization can make one special case look like a rule.
Wrapping also generalizes. Rather than leaving the edge of a small rectangle, a pointer that runs off the occupied region reappears on the other side by a defined rule. Anyone who has thought about a toroidal playfield in Befunge-93 will recognize the spirit, even though the details differ in an unbounded space.
Concurrency and extensions
Two parts of the design deserve a mention because they change how you think about a program. First, a single program can run several pointers at once, each with its own position and direction, using the idea of concurrent pointers. Second, a program can load named instruction sets, which is the subject of extension loading. Loading extensions raises real questions about portability, since a program that depends on one is only as portable as the interpreters that provide it.
Who should learn it, and how
Funge-98 is a good second step for someone who has finished the basics of Befunge and wants to see how a small language grows into a bigger one. It is also a case study in specification writing: what a good specification pins down, and what it leaves to implementers. If you plan to write an interpreter of your own, reading the specification closely is excellent practice, though a full implementation is a large project and many people stop at a useful subset.
A sensible path is to master plain Befunge, then add Funge-98 instructions one at a time: jumps first, then iteration, then the stack of stacks, and only later concurrency and fingerprints. Each addition is small on its own. The size of the specification comes from how many such pieces there are, not from any single one being difficult.