SNOBOL and Icon
SNOBOL (StriNg Oriented symBOlic Language) is a family of programming languages built at Bell Telephone Laboratories between 1962 and 1967 by David Farber, Ralph Griswold, and Ivan Polonsky — and Icon is its direct descendant, designed by Griswold at the University of Arizona in 1977–78. Between them they introduced two of the most quietly consequential ideas in the history of programming: the pattern as a first-class data type, and goal-directed execution driven by generators. Every programmer who has ever written a regular expression, or called a Python yield, is standing downstream of these two languages.
SNOBOL4, the mature form, was the most powerful text-processing language of its era — arguably of any era. It treated patterns not as strings of cryptic notation but as structured data that could be built, stored, passed to functions, and even modified while a match was in progress. Its matcher could express full Backus–Naur form grammars — a class of problem provably beyond ordinary regular expressions, which would not acquire comparable power for forty years. Icon took the same engine — success, failure, and backtracking — and wrapped it in the ALGOL-style syntax the industry had learned to expect, adding the generator, a construct so natural that Python's designers cited Icon by name when they adopted it in 2001.[1]
This article tells the whole story: the language itself, its history and lifetime, and the concepts it gave the world — pattern matching, goal-directed programming, generators, and the entire tradition of string-processing languages that followed.
The world before strings
To understand what SNOBOL did, you have to remember what programming looked like when it arrived. The languages of the 1950s were built for numbers. FORTRAN (1957) processed arrays of floating-point values; its string handling was, charitably, an afterthought — text lived in fixed-length fields manipulated through format statements. COBOL (1959) thought in records: fixed-layout rows of data for payroll and inventory. ALGOL (1958, 1960) gave the world block structure and recursion — and essentially no strings at all.
But computers were already drowning in text: programs themselves, data records, natural language. The first people to notice were the linguists. At MIT in 1957, Victor Yngve's group built COMIT, the first language designed specifically to manipulate strings — motivated by the dream of Machine translation, which in those optimistic years seemed a few years from solved. COMIT treated text as something to be rewritten by rules: match a fragment of the input against a pattern, replace it with something else, and repeat. That single idea — find this, replace it with that — is the seed of everything in this article.
COMIT was brilliant and awkward in roughly equal measure. Its notation was dense, its execution slow, and its portability nonexistent. A second early language, TRAC (1964), pursued macros and text generation. The stage was set for someone to do string processing properly — and the people who did were not linguists at all, but researchers at the most fertile laboratory in the history of computing.
Bell Telephone Laboratories in the 1960s was a place where a researcher could be handed a problem, a mainframe, and effectively no supervision. The Programming Research Studies department at the Holmdel, New Jersey site — six people — sat inside an institution that in a single decade produced the transistor's successors, Unix, C, information theory's mature form, and half the theoretical foundation of the digital century. Computing there meant Punched cards, batch queues, an IBM 7090 shared by a buildingful of researchers, and turnaround measured in the time it took to walk a card deck to the machine room and find your printout in a bin. Interactive terminals were a rumor. You got a few shots a day; each one had to count, which is precisely the environment in which dense, expressive notation thrives.
Bell Labs and the birth of SNOBOL

In the fall of 1962, three members of the six-person Programming Research Studies department at Bell Labs in Holmdel, New Jersey — David Farber, Ralph Griswold, and Ivan Polonsky — were frustrated. Their actual work involved the symbolic manipulation of polynomials, symbolic integration, and the study of Markov chains. Their tool was SCL, a language written by department head Chester Lee — slow, low-level, and producing "volumes of code for even simple projects." They considered adopting COMIT, found it wanting, and did what Bell Labs people did in that golden age: they wrote their own language.[2]
The first versions ran on the lab's IBM 7090 mainframe in early 1963, and by summer the language was in use across Bell. It had one data type — the string — no functions, no declarations, almost no error control, and a syntax of beautiful simplicity: every statement was a pattern match with an optional replacement and an optional branch. Its authors called it a personal tool. Tools that good never stay personal.
SEXI, or how SNOBOL got its name
The naming story is one of computing's great anecdotes, told by Farber himself. The team first settled on SEXI — "Symbolic EXpression Interpreter." All went well until the day Farber submitted a batch job; on the JOB card, in standard Bell Labs style, he punched the program name and his own: SEXI Farber.
"One of the Comp Center girls looked at it and said, 'That's what you think.'"
A new name was required. The team sat, talked, drank coffee, shot rubber bands. After far too long someone — most likely Ralph — said they didn't have "a snowball's chance in hell" of finding a name. The room yelled at once: SNOBOL — in the spirit of the era's "-BOL" languages. The expansion came after: StriNg Oriented symBOlic Language, a backronym stretched as far as it would go.[3]
The three authors

The trio behind SNOBOL each went on to notable careers. David J. Farber left Bell Labs for a long academic career — at UC Irvine, the University of Delaware, Carnegie Mellon, and finally the University of Pennsylvania, where he became one of the elders of computer networking. His students built early pieces of the Internet's infrastructure; the community nicknamed him, with affection, a grandfather of the Internet, and his Interesting People mailing list ran for decades as the industry's back channel. Ivan P. Polonsky continued at Bell Labs in language research; and Ralph E. Griswold — the member of the trio for whom string languages became a life's work — carried SNOBOL to the University of Arizona in 1971 and spent the next three decades extending the family through SL5, Icon, and Unicon. He died in 2006, having out-published, out-implemented, and out-taught nearly everyone in his niche. The SNOBOL lineage is unusual in language history for having a single continuous steward: nearly every idea in this article passed through one man's mind, twice, twenty years apart.
The versions: SNOBOL 1 through 4
SNOBOL evolved quickly — and its early history is a lesson in how languages actually grow.
SNOBOL1 (1962–63) was the personal tool: string processing with pattern matching and replacement, one datatype, minimal syntax, written in IBM 7090 assembly.
SNOBOL2 (April 1964) added built-in functions and the ability to link in external assembly code. It was used mostly inside Bell, though it reached as far as MIT's Project MAC. Built-in functions, once present, immediately taught users to want user-defined ones.
SNOBOL3 (July 1964) supplied exactly that — programmer-defined functions — and became genuinely popular. Other sites reimplemented it for other machines, and incompatible dialects bloomed. Success had created the classic problem: the authors were being bug-reported against versions they never wrote.
SNOBOL4 (1967) was the answer and the masterpiece. The team decided to define the language once, completely, and make it run everywhere — an extraordinary decision for 1967. The interpreter was written in assembly, but through assembler macros it targeted an abstract machine: the SNOBOL Implementation Language, or SIL, a generalization of string-manipulation macros by Douglas McIlroy — the same McIlroy who was then inventing pipes down the hall. To port SNOBOL4, you reimplemented the SIL macros on your machine; the whole language came along for free. SNOBOL4 was running on the IBM 360 in 1967 and was rapidly ported essentially everywhere. It is one of the earliest serious virtual-machine implementations in computing history — the JVM's ancestor, by two decades.[4]
It is worth pausing on what else existed in 1967, because SNOBOL4's ambition only registers against the backdrop. FORTRAN IV was five years old. BASIC was three. PL/I was new. ALGOL 60 had given the world recursion and blocks but no strings to speak of. LISP had symbolic computation and its own exotic syntax; Prolog was still five years in the future, unbuilt. Into that world landed a language with garbage collection, a portable virtual machine, programmer-defined datatypes, associative arrays, runtime code generation, and a pattern facility equivalent to context-free grammars — a feature list that reads like a 1990s scripting language's sales pitch, shipped when the moon landing was still two years away.
McIlroy struck twice. In 1969 he insisted SNOBOL4 add an associative-array type — the table — decades before "hash map" or "dictionary" became every language's standard feature. It arrived and stayed.
Under the hood: what SNOBOL4 could do
Behind the five-part statement sat an unusually modern machine. SNOBOL4 supported integers, limited-precision reals, strings, patterns, arrays, tables, and programmer-defined datatypes — the DATA function let a user declare record types with named fields, a facility comparable to COBOL's records and ahead of Pascal's. Everything lived in a single garbage-collected heap — automatic memory management on a 1967 mainframe, when most languages still treated memory as the programmer's problem.[5]
Most startling of all, SNOBOL4 strings could be turned into programs at runtime. EVAL evaluated a string as an expression, and the CODE function took a string of SNOBOL source, compiled it inside the running program, and returned it as a callable value — eval-style metaprogramming, or JIT-compilation from the user's seat, on a machine that cost millions and shared an hour among dozens of users. A program could write a program. This produced the celebrated SNOBOL foot joke: a program that reads its own source, strips every line containing the letter e, runs the result — and amputates itself, because a source file with every e removed is a foot short. Dr. Dobb's commemorated the genre as "Programs That Transform Their Own Source Code"; SNOBOL4 made such self-modification routine enough to joke about.EVAL/CODE self-modification tradition.">[6]
The SPITBOL extensions, later absorbed into every modern implementation, pushed further still: nested conditional expressions, immediate assignment during matching, and the ability for a function called mid-pattern to alter the pattern being matched. A SNOBOL4 pattern was less a query than a live computation with side effects — the pattern could think about itself while it ran.
What a SNOBOL program looks like
SNOBOL is column-oriented — a punched-card-era language — and every statement has the same five parts, all optional:
A label marks a jump target. The subject is the string under examination; the pattern is what to match against it; = object replaces whatever matched; and the : transfer sends control to a label on success :S(...), on failure :F(...), or unconditionally. That is the entire language's control flow: there is no if, no while, no for — only match, and branch on the outcome.
OUTPUT = "Hello, World!"
END
Hello World is one assignment to the pseudo-variable OUTPUT, which prints whatever is assigned to it. Something with a little motion — greet the user differently by initial:
OUTPUT = "What is your name?"
Username = INPUT
Username "J" :S(LOVE)
Username "K" :S(HATE)
MEH OUTPUT = "Hi, " Username :(END)
LOVE OUTPUT = "How nice to meet you, " Username :(END)
HATE OUTPUT = "Oh. It's you, " Username
END
Line three matches Username against the pattern "J" — implicitly anchored, so it matches only if the name begins with J. On success it jumps to LOVE; otherwise it falls through to the next line. The :(END) is an unconditional transfer. A program that keeps reading until the input runs out shows the idiom at full strength — LEN(1) is a pattern that succeeds only if at least one character remains:
OUTPUT = "Press return alone to finish"
NameCount = 0 :(GETINPUT)
AGAIN NameCount = NameCount + 1
OUTPUT = "Name " NameCount ": " PersonalName
GETINPUT OUTPUT = "Name please: "
PersonalName = INPUT
PersonalName LEN(1) :S(AGAIN)
OUTPUT = "Finished. " NameCount " names requested."
END

: transfer column are a card-format language's grammarIt looks alien because it is alien — this is programming as a sequence of rewrite rules, closer in spirit to COMIT and to Prolog's clause logic than to anything ALGOL-shaped. The same five-part line handles pattern matching, substitution, I/O, and every conditional and loop the program will ever need.
Pattern matching
Pattern matching is SNOBOL's reason to exist, and the reason it still matters. The idea generalizes what a regular expression does — find structure in text — and lifts it into the language itself.
A SNOBOL pattern is a first-class data type: a value like a string or a number, stored in variables, passed to functions, returned from functions, concatenated into larger patterns, and built at runtime. Two operators construct them: concatenation (adjacency — A B matches A then B) and alternation (the | operator — A | B matches A or B). Patterns nest freely. This looks ordinary now because JavaScript regex literals and parser combinator libraries made it ordinary. In 1967 it was a decade ahead of everyone.
The matcher itself is a backtracking engine — the same algorithmic family as Prolog's resolution, developed in the same years. Try an alternative; if the match later fails, back up and try the next. SNOBOL4 patterns can capture substrings during the match (pattern . variable binds the matched text), invoke user functions mid-match that can steer or even rewrite the pattern while it runs, and express recursive structures: a pattern can contain a reference to itself. That last property is the crucial one — it lets a SNOBOL pattern describe a full context-free grammar, the same class as Backus–Naur form. A SNOBOL program could implement a language interpreter almost directly from its published BNF; a macro assembler for a theoretical machine was reportedly a few hundred lines, with each new instruction costing one line.[7]
Regular expressions, by contrast, are regular — the name is a theorem, not a description. They cannot match balanced parentheses, cannot parse a grammar, cannot recurse. They were good enough for "find text like this" and so they won the popular market; AWK and later Perl carried them to ubiquity in the 1980s and 90s while SNOBOL's richer model faded from teaching. Only in December 2007, with recursive patterns in Perl 5.10, did the mainstream finally acquire what SNOBOL4 had shipped in 1967 — a forty-year gap in which the less capable tool was simply the fashionable one.(?R) recursion (December 2007); Gimpel 1973 supplies the theory.">[8]
* a SNOBOL4 pattern for "word word" — a doubled word
* built as data, matched as structure
TWO = BREAK(" ") . FIRST " " *FIRST
LINE "the the end" TWO :S(DOUBLE)
OUTPUT = "no doubled word" :(END)
DOUBLE OUTPUT = "doubled: " FIRST
END
Here BREAK(" ") . FIRST matches up to a space and captures it into FIRST, " " matches the space literally, and *FIRST matches the captured text again — the pattern reads like the sentence it describes. A practical parser for "a complete name and international postal mailing address" — the example the literature liked to give — is expressible the same way, and was.
The primitive vocabulary
Real patterns are assembled from a small vocabulary of built-in matchers, each one a generator of possible spans:
| Primitive | Matches |
|---|---|
LEN(n) | any n characters |
SPAN("0123456789") | a run of digits — longest possible |
BREAK(" .") | everything up to a space or period |
ANY("aeiou") | exactly one vowel |
NOTANY("012") | one character that is not a digit |
ARB | anything — the reluctant wildcard |
REM | the remainder of the string |
POS(0), RPOS(0) | anchored: start / end of subject |
BAL("()") | a balanced-parentheses expression — the showcase recursive primitive |
FAIL, SUCCEED, ABORT | control the match engine itself |
BAL deserves the spotlight it always gets: matching balanced delimiters is the canonical problem that breaks regular expressions, and SNOBOL4 shipped it as a builtin. Combined with conditional captures — pattern . variable binds text on success, pattern $ variable binds cursor position — and the alternation/concatenation operators, the vocabulary scales from tokenizing a line to parsing a language. Patterns being data, a program could store a library of grammar fragments in a table and compose full parsers at runtime:
DIGIT = ANY("0123456789")
INT = POS(0) SPAN("0123456789") RPOS(0)
INPUT "4096" INT :S(ISINT)
OUTPUT = "not an integer" :(END)
ISINT OUTPUT = "integer!"
END
Scale that same technique to a real grammar and the machinery shows its muscle. A date parser — "25 December 1745" — is a handful of pattern definitions, each readable as what it describes:
DIGITS = "0123456789"
DAY = POS(0) SPAN(DIGITS) . N " "
MONTHS = "January" | "February" | "March" | "April"
+ | "May" | "June" | "July" | "August"
+ | "September" | "October" | "November" | "December"
DATE = DAY MONTHS . M " " SPAN(DIGITS) . Y RPOS(0)
INPUT DATE :S(OK)
OUTPUT = "not a date" :(END)
OK OUTPUT = N " of " M ", " Y
END
+ continues a definition on the next line. The whole thing — grammar definition, match, capture, and formatted output — fits in a dozen lines, and the pattern DATE is itself a value that could be stored, combined, or passed elsewhere. This is the difference a first-class pattern type makes: a regex solution embeds the same logic as one unreadable string; the SNOBOL version is a grammar, composed like a grammar, debugged like data.
Text processing languages
SNOBOL4 became the canonical text-processing language — the tool for the jobs the numeric languages couldn't see. The pattern fit a niche that was exploding in the 1970s: the Digital humanities, before the field had that name. Humanists needed to index, collate, translate, and transform text at scale — concordances, stylistic analysis, machine-translation experiments, catalogues — and SNOBOL4 was essentially the only serious instrument. It was taught widely at American universities in the late 1960s and early 1970s, and used through the 1970s and 80s; Susan Hockey's SNOBOL Programming for the Humanities (Clarendon Press, 1985) is the period's standard textbook.[9]
Its second home was language research itself: compilers, formal grammars, and early artificial intelligence — especially machine translation and natural-language comprehension, whose research community ran on the PDP-10 machines where SNOBOL4 lived comfortably. The file editor of the Michigan Terminal System adopted SNOBOL4 patterns as its search language — an editor whose regex equivalent was a full grammar engine.
The teaching footprint mattered as much as the research one. A generation of students met serious string handling through SNOBOL4 in the late 1960s and early 70s — the same years their engineering classmates were meeting FORTRAN. Three books did the carrying: the "green book" itself (Griswold, Poage & Polonsky's The SNOBOL4 Programming Language, 1968, with its famously rigorous-but-readable exposition), Griswold's own Macro Implementation (1972) for the internals-curious, and Gimpel's Algorithms in SNOBOL4 (1976), a genuine algorithms text that happened to be written in a pattern language. Emmer's SNOBOL4+ (1985) carried the language onto personal computers, and Hockey's humanities text into seminar rooms where the machine had previously been a punch-card curiosity. For a niche language, SNOBOL4 was unusually well-documented — one reason it still reads well today.
The genre SNOBOL4 defined has a recognizable genealogy afterward: AWK (1977, also from Bell Labs) streamlined the match-and-act model for line-at-a-time files; Perl (1987) fused it with regex and shell convenience into the web-era glue language; and every modern "text manipulation" facility — sed, grep, Python's re, JavaScript's regexes, jq — lives somewhere on the spectrum SNOBOL4 staked out.
Why the better tool lost
It is worth asking plainly why SNOBOL4 faded while objectively weaker tools prospered, because the answer is a standing lesson in language history:
- Syntax carried the era's fingerprints. Column layout and label-branch flow belonged to punched cards; once
if/then/whilebecame the industry's muscle memory, SNOBOL's transfer column read like assembly. - Regular expressions were smaller. For 90% of real work — find this string, split this line — a compact notation that fit inside an editor beat a grammar engine. The market for "a complete name and international postal mailing address" was real but narrow.
- AWK and Perl were free and on the machine you already had. Unix made them ambient; SNOBOL4 remained a language you installed deliberately.
- No champion survived. When Griswold's group moved on to Icon, SNOBOL lost its research engine. Perl had Larry Wall writing annual State of the Onion addresses; SNOBOL had a library of excellent books and no marketing department.
The pattern recurs throughout this encyclopedia: technical superiority loses to distribution, convention, and luck — which is exactly why preserving the knowledge matters. The better tool didn't disappear; it just stopped being looked at.

Implementations and dialects
The classic SNOBOL4 ran on the PDP-10 — slowly, because a portable interpreter pays in cycles. James Gimpel fixed that twice. In 1972, at Bell Labs Holmdel, he designed SITBOL, a native PDP-10 implementation, and used it as the semester project for a string-processing course at Stevens Institute of Technology (the "ST" in the name): students each implemented a slice in PDP-10 assembler, and the finished interpreter was a full-featured, high-performance SNOBOL4. Gimpel's greater work was SPITBOL — the compiled implementation that gave SNOBOL4 near-native speed and became the reference implementation for decades; after years as a commercial Catspaw product, SPITBOL was released as free software under the GNU GPL in April 2009.[10]
The ecosystem produced its own odd children. Snostorm (1970s, Fred Swartz, University of Michigan) was a preprocessor adding structured-programming constructs to SNOBOL for MTS sites. Snocone (Andrew Koenig, 1985) went further — a self-contained block-structured language on SNOBOL semantics. Minnesota SNOBOL4 by Viktors Berstis reproduced the IBM mainframe original most faithfully on PCs, down to Fortran-style FORMAT support. Catspaw, Inc. sold commercial ports for DOS, Macintosh, Sun and RS/6000 — all now free. GNU's Ada compiler carries GNAT.Spitbol, the SPITBOL string semantics callable from Ada. And the language runs today: Macro SNOBOL4 by Phil Budne and the BSD-licensed CSNOBOL4 port keep the original Bell Labs implementation compiling wherever C exists.

Griswold goes west: SL5
In August 1971, Ralph Griswold left Bell Labs for a professorship at the University of Arizona, bringing SNOBOL4 with him — and National Science Foundation support to keep evolving it. By then the language's design debts were obvious. Its column format and label-driven branching belonged to the punched-card age; structured programming — if/then, while, blocks — had become table stakes since ALGOL 60. SNOBOL4's semantics were brilliant and its syntax was dead.
Griswold's first attempt at a successor, SL5 ("SNOBOL Language 5," 1977), tried to graft the success/failure machinery onto conventional control structures. He judged the result a failure — the mechanisms fought each other. In 1977 he went back to first principles and set the constraints for the real successor: keep SNOBOL4's philosophical and semantic basis; take SL5's syntax and its features; drop the over-general procedure mechanism.[11]
The new language was SNOBOL5 for a while, but it had drifted too far from the name. They considered s — an homage to c, a sibling tribute to C — and abandoned it as untypesettable. Irving and bard were proposed and dropped; "TL" — "The Language" — was too coy. Then Xerox PARC's graphical-interface work put the word icon into the computer lexicon, and the name was chosen — a decision Griswold later regretted, since "icon" had no graphical features whatever and the name confused everyone it attracted.[12]
Icon
Icon (1978) is the idea of SNOBOL rebuilt for the structured-programming era: Pascal-flavored syntax (:=, procedure, end) with C's braces and a main procedure, dynamically typed, no declarations, automatic conversion between numbers and strings. On the surface it looks like a pleasant scripting language of its decade. Underneath it runs the strangest and most elegant control model any mainstream-adjacent language has ever shipped.
Goal-directed programming
In conventional languages a lookup that finds nothing returns a sentinel — -1, null, EOF — and the programmer writes tests everywhere: if (pos == -1), while ((c = read()) != EOF). In SNOBOL, an operation that couldn't produce a result failed, and the :S(...)/:F(...) transfers steered execution by it. Icon keeps the semantic — an expression succeeds with a value, or fails — and wires it into ordinary structured syntax. if, while, every, and friends are all driven by success and failure rather than by Boolean tests.
The payoff is concrete. File-copying in Java requires the EOF sentinel and an explicit comparison; in Icon it is:
while write(read())
read() produces a line, or fails at end of file; failure propagates through write into while, which stops — correctly, silently, by design. Comparisons work the same way: a < b is an operator that succeeds and returns b, or fails — so a < b < c does exactly what it looks like, since the first comparison hands its second operand to the second. And failure is not an exception: reaching end of file is an expected outcome, not a thrown emergency. Icon simply declined the sentinel-and-test industry that occupied every other language of its generation.[13]
Backtracking completes the picture: when a branch fails, Icon can rewind to an earlier point and try another alternative — and reversible assignment (<-, <->) exists so that variables changed inside a failed computation restore themselves, a built-in atomicity that string scanning relies on constantly:
{
i <- 10 &
j <- find(pattern, inString)
}
If find fails, the block fails — and i <- 10 rolls itself back, leaving no phantom assignment behind. In a language without reversibility, a failed parse attempt leaves the cursor wherever the attempt abandoned it, and the next attempt starts from a corrupt state. Icon's scan either commits its cursor movement or undoes it, which is exactly the semantics a backtracking parser wants and exactly what every hand-written regex loop gets subtly wrong.
One more control-flow subtlety separates Icon from every neighbor: every and while look alike but are not. while e re-evaluates e until it fails — its job is repetition. every e drives a generator, fetching the next result on each pass — its job is enumeration. every write(i to j) and while are the difference between "give me everything this can produce" and "keep doing this until it stops working." The distinction matters because an Icon programmer is always asking the same question: does this expression still have something to give?
Generators
If goal-directed execution is Icon's engine, the generator is its greatest export. In Icon, an expression doesn't evaluate to a value — it produces a result sequence: every value it could produce, yielded one at a time to whatever asked. find("the", s) doesn't return the first position of "the" and stop; it generates positions — 4, then 29 — and when it has no more to give, it fails. The every construct consumes a sequence:
s := "All the world's a stage. And all the men and women merely players"
every write(find("the", s))
Two lines, and every occurrence is printed — no index variable, no -1 sentinel, no loop bookkeeping. Where other languages' indexOf requires a three-parameter overload and a hand-rolled loop, Icon's generator simply keeps answering until it can't.
User procedures become generators with suspend, which yields a value and parks execution mid-procedure until resumption — a return that doesn't destroy state:
procedure ItoJ(i, j)
while i <= j do {
suspend i
i +:= 1
}
fail
end
Call ItoJ(1, 5) under every and it yields 1, suspends; resumes, yields 2; and so on, until fail ends the sequence. Add the alternator | — which looks like or but actually generates its operands in turn — and to for integer ranges, and iteration collapses to intent:
every write(1 to 10)
every i := (1 | 3 | 4 | 5 | 10 | 11 | 23) do write(i)
every x := ItoJ(0,10) & x % 2 == 0 do write(x) # evens only
If this sounds like Python's yield, that's because it is. When Python adopted generators in PEP 255 (2001), its authors listed Icon among the direct inspirations — the mechanism a generation of Python programmers know as laziness was running in Tucson two decades earlier. The same DNA surfaces in Jq's stream semantics and the Icon-descended Goaldi. Generators are now the standard answer to "iterate without materializing"; Icon was the proof of concept, complete with the coroutine machinery (suspend/resume) that modern languages still wrap in iterators and async.[14]
String scanning
Icon's third pillar is the string scanning environment: s ? expr binds s as the subject for a block of string operations, with two implicit variables — &subject and &pos (the cursor) — doing the bookkeeping that string parsing always makes explicit. Inside ?, functions like tab (move the cursor), many (skip a run of a character set), upto (find the next member of a set), match (literal string at cursor), and pos (test cursor position) compose into parsers of startling brevity. Words from a line:
s ? {
while not pos(0) do {
tab(many(' ')) # skip blanks
word := tab(upto(' ') | 0) # grab up to the next blank or end
write(word)
}
}
The same machinery that powered SNOBOL4 patterns — success, failure, cursor backtracking — is all here, just recast in functions on an implicit subject instead of a pattern datatype. An Icon string scanning block for a real grammar (the canonical example parses date strings like "Mon Dec 8" with a twenty-line matcher) is the lineal descendant of SNOBOL's BNF-as-pattern, traded down in raw power for a large gain in readability.
The payoff shows most clearly in the classic utility program — a word-frequency counter, the kind of thing awk people write to show off. In Icon the whole job is twenty lines and most of it is the sorting:
procedure main()
counts := table(0) # default value 0 for new keys
every line := !&input do { # generator reads the stream
line ? while tab(upto(&letters)) do {
counts[tab(many(&letters))] +:= 1
}
}
pairs := []
every word := key(counts) do push(pairs, [word, counts[word]])
every p := !pairs do write(right(p[2],6), " ", p[1])
end
table(0) is a map whose missing keys default to zero; key generates the table's keys; the scanning block walks each line pulling alphabetic words. No regex literals, no split/join ceremony — the same job that takes a page in most languages' standard style is a paragraph here, and the paragraph is still readable.
Structures and strings
Icon's collections were equally prescient: lists usable as arrays, stacks, and queues; tables — the associative arrays McIlroy forced into SNOBOL4, here a first-class citizen; sets with union ++, intersection , difference --; and csets**, character sets like &digits, &lcase, and user-defined 'aeiou', built for the scanning operations. Strings are indexable between characters (position 1 is before the first character, position 0 after the last), sliceable from either end, and mutable through their subscripts — s[2] := "123" inserts into the middle of "abc". Everything iterable is a generator, down to !list producing a list's elements and !"Hello" producing a string's characters. Even &input — standard input — is a generator: every push(lines, !&input) reads a whole stream into a list in one expression.
For completeness, Icon also shipped co-expressions — first-class coroutine objects that capture a suspended computation and can be resumed explicitly with @. Generators get their values for free, in lexical order; a co-expression gets them on demand, from wherever you like, making it the general mechanism beneath suspend and the direct ancestor of the coroutine/yield machinery modern languages expose directly. It is one more case of Icon quietly shipping in 1978 what other languages would spend the next four decades rediscovering piecemeal — first as iterators, then as generators, then as async.
SNOBOL4 and Icon side by side
| SNOBOL4 (1967) | Icon (1978) | ||
|---|---|---|---|
| Surface | Column-format, labels and :S/:F transfers | ALGOL/Pascal-flavored blocks, procedure, := | |
| Control model | success/failure branching | success/failure everywhere — goal-directed | |
| Pattern facility | patterns as first-class data, full context-free power | string scanning: ?, &subject, &pos, tab/many/upto | |
| Iteration | manual loops via transfers | generators — every, to, ` | , !, suspend` |
| Data | strings, numbers, arrays, tables, DATA records | lists, tables, sets, csets, records, co-expressions | |
| The trade | maximum expressive power | most of the power, dressed for the structured-programming era |
The two are not rivals but stages of one idea: SNOBOL4 proved that matching and failure could be a programming language; Icon proved that idea could wear the clothes of a normal one.
Criticisms
An honest account has to include what went wrong. Laurence Tratt's 2010 analysis of Icon's design is the standard critical text, and its two main findings are instructive.[15]
First, the default-fail convention: a procedure that runs off its end returns &fail. Elegant for generators, it makes x := f(-1) a silent no-op — x keeps its old value, no warning — and Tratt found the vast majority of real Icon procedures are not generators, so the language's default behavior optimizes for the minority case while creating a subtle trap in the majority.
Second, the absence of Boolean logic creates edge cases of its own: if c then ... succeeds even when c was never assigned, because an unassigned variable's value (&null) is still a value — so the test must be written if /c then ... or c === &null. Icon traded Boolean complexity for failure propagation, and mostly won — but not everywhere, and not free.
The fair summary is the one Icon's own community reaches: for the domain it was built for — strings, scanning, search — goal-directed code is shorter, clearer, and harder to get wrong than anything before or since. For general-purpose programming, the same rules occasionally surprise. The idea was too good for its medium.
Unicon and today
Icon's lineage continues. Unicon (from Idol, the 1996 object-oriented extension) adds objects, networking, databases, and concurrency to the core language and remains actively developed. The reference Icon implementation itself is still maintained — release 9.5.25a shipped in September 2025, forty-seven years after the language was designed. SNOBOL4 runs wherever CSNOBOL4 compiles; Griswold's implementation and books remain available; and the University of Arizona keeps the Icon project pages that the language's researchers built. These languages are not specimens under glass. They compile, they run, and their maintainers still ship releases.
Running it today
Every implementation mentioned here is free:
- SNOBOL4 — CSNOBOL4 (BSD-licensed port of the Bell Labs original, builds anywhere C exists), Macro SNOBOL4 (Phil Budne's portable C implementation), SPITBOL (GPL since 2009, the fastest by far), and the faithful Minnesota SNOBOL4 for PC-era fidelity. The clearinghouse is
snobol4.org; the preservation mirror isregressive.org/snobol4. - Icon — the reference implementation from the University of Arizona Icon project (
www.cs.arizona.edu/icon), plus Jcon for the JVM. The Griswolds' The Icon Programming Language (3rd ed., 2002) is the book, and the Arizona site hosts the documentation set. - Unicon —
unicon.org, for Icon with objects, POSIX facilities, and a standard library the original never needed.
The classic texts remain findable: the "green book" — Griswold, Poage & Polonsky, The SNOBOL4 Programming Language (1968) — Griswold's The Macro Implementation of SNOBOL4 (1972) for the virtual-machine internals, Gimpel's Algorithms in SNOBOL4 (1976), and Hockey's SNOBOL Programming for the Humanities (1985) for the period's applied tradition. Griswold's own "A History of the SNOBOL Programming Languages" (1978) and the HOPL volume chapter are the primary-source history — this article leans on them throughout.
Language history: what the line taught us
Placed end to end, the SNOBOL–Icon story is a compressed history of how programming-language ideas actually travel. A concept appears (COMIT's rewrite rules), is perfected in a form the mainstream can't absorb (SNOBOL4's pattern datatype on a 1967 mainframe), is rediscovered in diluted form by fashionable successors (AWK's patterns, Perl's regexes), and is finally re-embedded so quietly that its users never learn where it came from (Python's yield, jq's streams, every parser-combinator library on Earth).
There is a subtler lesson in the lineage, too: ideas persist better than implementations. SNOBOL4 the artifact is a curiosity — column-format, mainframe-bound, its idioms extinct. But the idea the artifact carried turned out to be load-bearing. It survived a syntax change (Icon), survived being renamed (generators), survived being diluted (regex), and surfaced again every time the industry rediscovered that text is most of what computers actually process. When Lua's designers wrote their HOPL history, they listed SNOBOL among their language's influences — the pattern tradition reaching even the embeddable-scripting niche by way of its reputation. When Stephen Bourne needed a Unix shell scripting language in the same Bell Labs building where SNOBOL was made, the result, bs, borrowed SNOBOL-flavored features outright. The family touches nearly every string-handling idiom in daily use.
Three of the modern programmer's daily tools descend directly from this family:
- Pattern matching — SNOBOL4 defined the problem space regular expressions still occupy, and its context-free power remains beyond stock regex forty-five years later.
- Generators — Icon's
suspend/resumeis Python'syield, and the lazy sequence is now how the industry thinks about iteration. - Goal-directed evaluation — success/failure as a control primitive previews today's result types and early-return styles (
Resultin Rust,err == nilin Go) — the same instinct: make failure a value, and let the program steer by it.
The languages themselves, meanwhile, simply persisted — maintained, ported, free, and still taught to anyone willing to look back. Text didn't stop needing processing in 1967, and the tools Bell Labs and Tucson built for it have never actually been improved upon at the things they were built for.
And one more thing persists: the record itself. Griswold wrote his history in 1978, while the story was still warm. The green book is still readable. The SPITBOL source still compiles. The Arizona Icon pages still serve. SNOBOL and Icon are among the best-preserved languages of their generation — documented by their own authors, in their own words, with the source still runnable. That is what preservation looks like when it works. Knowledge is only ever lost when the world stops looking — and pages like this one exist to make sure it doesn't.
See also
- FORTRAN — the numeric world SNOBOL answered to
- Ada (programming language) —
GNAT.Spitbolcarries SNOBOL4's semantics into Ada - History of Programming — the larger map this lineage belongs to
- Chevalier de Saint-Georges — on preserving people history nearly lost; languages deserve the same
- REBOL — the messaging branch of the same data-is-code tradition
Footnotes
- ↑ PEP 255, "Simple Generators" (Schemenauer, Peters, Hetland, 18 May 2001), lists Icon among the generators' direct inspirations.
- ↑ Ralph E. Griswold, "A History of the SNOBOL Programming Languages," ACM SIGPLAN Notices 13:8 (August 1978), and the HOPL paper Griswold (1981) — the standard primary sources on SNOBOL's origins.
- ↑ David Farber, posting to his Interesting People mailing list, 26 December 2008 — the first-person account of the SEXI card and the snowball's chance. The canonical backronym appears in the Encyclopedia of Computer Science and Technology, vol. 13 (1979).
- ↑ Ralph E. Griswold, The Macro Implementation of SNOBOL4 (W.H. Freeman, 1972) — the definitive account of the SIL virtual machine. McIlroy's second contribution came in 1969, when he insisted the language gain the associative-array "table" type.
- ↑ SNOBOL4's datatype system and single garbage-collected heap — Griswold, Poage & Polonsky, The SNOBOL4 Programming Language (Prentice Hall, 1968), the canonical "green book."
- ↑ "Dr. Dobb's: Programs That Transform Their Own Source Code; or: the Snobol Foot Joke" — the
EVAL/CODEself-modification tradition. - ↑ James F. Gimpel, "A Theory of Discrete Patterns and their Implementation in SNOBOL4," Communications of the ACM 16:2 (February 1973), 91–100 — the formal treatment establishing that SNOBOL4 patterns subsume context-free grammars.
- ↑ The recursive-pattern gap: SNOBOL4 (1967) vs. Perl 5.10's
(?R)recursion (December 2007); Gimpel 1973 supplies the theory. - ↑ Susan M. Hockey, SNOBOL Programming for the Humanities (Clarendon Press, 1985) — the humanities-computing standard text; also Gimpel's Algorithms in SNOBOL4 (Wiley, 1976) and Griswold's String and List Processing in SNOBOL4 (Prentice Hall, 1975).
- ↑ Gimpel's SITBOL course implementation (1972, Stevens Institute of Technology) and SPITBOL's history through its 2009 GPL release.
- ↑ Ralph E. Griswold and David R. Hanson, "An Overview of SL5," ACM SIGPLAN Notices 12:4 (April 1977), and Griswold & Griswold, The Icon Programming Language, 3rd ed. — on SL5's lessons and Icon's design constraints.
- ↑ Griswold on the naming in a 1985 interview — the 'icon' term collision with the GUI usage from Xerox PARC.
- ↑ Icon's goal-directed model per Griswold & Griswold, The Icon Programming Language, 3rd ed. (2002), and Laurence Tratt's retrospective analysis (2010).
- ↑ PEP 255 naming Icon as an inspiration for Python's generators; Icon's suspend/resume as user-level coroutines — Griswold & Griswold 2002.
- ↑ Laurence Tratt, "Experiences with an Icon-like expression evaluation system" (2010) — the standard design critique.