Guy Steele had a hand in Scheme, Common Lisp, the Java Language Specification and Fortress. In October 1998 he gave the OOPSLA keynote under an odd constraint: he could use any word of one syllable freely, but every longer word had to be defined first, out loud, from words he’d already defined. The constraint is the argument. Watching him build up “woman”, “number”, “machine”, “definition” and finally “pattern” from a small base vocabulary shows the audience what it’s like to grow a language from a small core. That’s what he wants Java to do, and what he says every language now has to do. This is the Classic of the Week.
A small vocabulary, grown in front of you
The first ten minutes are definitions. A machine is “a thing that can do a task with no help, or not much help, from a person.” Numbers are built Peano-style: zero (“not”), or one more than a number. Then he defines a toy machine with states, counters and “up”/“down” instructions, and says a computer is any machine that can do at least what that one can. Only after that does he define primitive: a word we can take for granted. For this talk the primitives are all words of one syllable.
He doesn’t pretend this is free. Some ideas that feel primitive aren’t, and have to be defined again in each new program. His example is max, which he thinks of as primitive but few languages give you. That point comes back later. One-syllable English turns out to be a richer vocabulary than Ogden’s Basic English, because Basic English keeps long Latinate words and so never feels like real English to a native speaker. A small base works only if the words you add feel like part of the language.
Small with warts, or big and late
Steele points at his friend Dick Gabriel in the front row and summarises Worse Is Better: in a race, “a small language with warts will beat a well-designed language because users will not wait for the right thing,” and once a small language fills a niche it’s hard to dislodge. Could a small language without warts win? Twenty-five years earlier maybe (“Scheme was my best shot at it”), but users in 1998 want graphics, networking, dynamic code loading, untrusted code, threads, many machines and every human language’s text. A small language can’t do all that, and a big one takes too long to ship.
His way out is in the next sentence. The language must start small and grow as its user base grows. “I now think that I as a language designer helping out with the Java programming language need to ask not should the Java programming language grow, but how should it grow.”
User code has to look like the language
There are two kinds of growth: adding vocabulary (libraries) and changing the rules of meaning. A true library only adds words, and its words should look exactly like the language’s primitives. APL is the cautionary example. Steele loves it, but in APL a user-defined function doesn’t look like a built-in operator, so users couldn’t grow the language smoothly. Lisp grew much faster because user code was indistinguishable from the core, so people could try things out and share the good ones. One part of Lisp spread to almost every language that followed it: garbage collection, which he leaves to the audience to define in words of one syllable “as a task to try in your spare time.”
The cathedral, the bazaar, and a master plan
On who does the growing, Steele brings in Eric Raymond’s essay (defining cathedral and bazaar first) and argues for the Linux model: put the source code out there, but have someone in charge “who is a quick judge of good work and who will take it in and shove it back out fast.” He then reads a Christopher Alexander quote on master plans by rote, joking that he can’t understand it because Alexander didn’t define his long words first:
“Under a master plan people are living with a frozen future, able to affect only relatively trivial details.”
His conclusion isn’t to stop designing. “Instead of designing a thing, you need to design a way of doing”, one that makes some choices now and leaves slots for others to fill later. That leads to the word the audience has been waiting for, pattern, defined as a plan with parts, relations between them, and holes where other things can go.
Generic types and operator overloading
The concrete proposal for Java is small. Add generic types and user-definable operator overloading, and “we will not need to grow it in a hundred other ways.” He backs this with a run of number types that some users badly want and most never touch: complex numbers, rational numbers, intervals, vectors, matrices, and Conway’s surreal-like numbers for game theory (of which “three persons in the world” know the use). None of them belongs in the core. All of them can live in libraries, but only if user-defined numeric types can be written a + b rather than a.add(b). Java’s BigInteger was his evidence: the class existed, and the people who had to use it complained about the method-call syntax.
Java got generics six years later. It still doesn’t have operator overloading, and arguments about value types and numeric libraries on the JVM still cite this talk.
A language design is a pattern for growth
The central passage is this:
“A language design can no longer be a thing. It must be a pattern, a pattern for growth, a pattern for growing the pattern for defining the patterns that programmers can use for their real work.”
Every good programmer, he adds, already does language design, “though not from scratch,” by building a working vocabulary on top of a base. The designer’s job is to give them the tools to make that vocabulary look native: a good type system, ways to define new types, ways to add words and rules. The designer should not, for example, put twenty number types in the core. Users will all ask for different ones, so give them the means to build their own.
He closes by reflecting on the constraint itself. Writing in short words forced him to decide, word by word, whether a new definition was worth the cost, which is the same trade-off a language designer faces with every feature. He suggests, half joking, that lawmakers be required to speak in words of one syllable, because “this mode of speech makes it hard to hedge… if you do not veer wide of the truth you are forced to hit it dead on.”
Key takeaways
- The talk’s form makes its point. Starting from one-syllable words and defining everything else shows what growing a language from a small core actually involves.
- A language has to start small, because big languages ship too late, and it has to grow, because small languages can’t meet modern needs. The design question is how it grows, not whether.
- Words defined by users should be indistinguishable from the language’s primitives. APL failed this test and Lisp passed it, and that largely explains which one users extended.
- Growth works best with open source plus someone in charge who quickly accepts good contributions and ships them, in the style of Linux.
- Generic types and operator overloading were Steele’s minimal Java proposal, because together they let users add numeric and collection types without changing the core.
- A language design should be a pattern with slots left open for later choices, not a finished master plan. Alexander’s warning about a “frozen future” applies to languages as much as to towns.
Source
- Talk: “Growing a Language” (OOPSLA ‘98 keynote)
- Speaker: Guy L. Steele Jr. (then Sun Microsystems)
- Event: ACM OOPSLA 1998, Vancouver
- Length: 54 minutes
- Archive: University Video Communications, published by the Computer History Museum
- Video: https://www.youtube.com/watch?v=lw6TaiXzHAE
- Paper: Steele, “Growing a Language”, Higher-Order and Symbolic Computation 12, 221–236 (1999)