Arc
Arc is Paul Graham and Robert Morris's minimalist Lisp dialect, built on Racket and best known as the language Hacker News is written in - a deliberately small, unfinished, terseness-obsessed experiment in how few characters a working program can take.
Created by Paul Graham and Robert Morris
Arc is a dialect of Lisp designed by Paul Graham and Robert Morris, first released publicly on January 29, 2008 after roughly seven years of private development. It is small - the core library is roughly a couple of thousand lines of Arc sitting on a comparable amount of Racket - and it is unapologetically unfinished. Graham released it with only ASCII string support, no module system, no libraries to speak of, and a note that it was aimed at people who would be comfortable with all of that.
What makes Arc worth studying is not the feature list. It is that Arc is a language designed around a single metric - how few characters do you have to type to write a working program - by someone who then wrote a real, heavily-trafficked web application in it and left the source in the box. Hacker News is written in Arc, and news.arc ships inside the official tarball. Very few language designers have been that publicly accountable to their own design.
History and Origins
Graham announced in 2001 that he was working on a new Lisp dialect. The essays that followed - Being Popular (May 2001), The Hundred-Year Language, Revenge of the Nerds - functioned as a design document written in public. The argument running through them is roughly: languages are adopted by good programmers writing exploratory code, good programmers want brevity and power rather than protection, and the way to win is to be terse, hackable and free.
The seven years between announcement and release did enormous damage to expectations. By 2008, Arc had been anticipated long enough that people expected a finished language. What arrived was a small Lisp on top of MzScheme with ASCII-only strings.
The reception was, at best, mixed. The Unicode omission drew the sharpest criticism, and the criticism was substantive rather than merely irritable: character encoding is one of the few things that genuinely cannot be bolted on by a library later, because every string operation in the language and every library built on those operations bakes in the assumption. Others argued that Arc was not a new language at all but a layer of macros over Scheme. Graham’s public response - essentially that his earlier work had been criticised too - did not settle the argument.
Robert Morris’s role deserves more billing than it usually gets. The copyright notice in the distribution names both men, the compiler work on the Racket side is largely his, and the 2009 port to MzScheme 4 - the change that kept Arc runnable on a supported Scheme - was done by Morris with help from Racket developer Eli Barzilay.
Design Philosophy
Brevity is the metric. Graham has argued that programmers choose languages partly on the total number of characters they will have to type. Arc takes this seriously to a degree that is genuinely unusual: def not define, is not eq?, no not null?, fn not lambda, t and nil back from Common Lisp because they are one and three characters. This is not laziness dressed up as philosophy - it is a bet that terseness at the token level compounds into shorter, more malleable programs.
Exploratory programming over defensive programming. Arc has no module system, no access control, no immutability guarantees and no type declarations. Every one of those is a feature designed to protect large teams and long-lived codebases from themselves. Arc’s target user is a small number of people writing a program they are still figuring out. Graham’s phrase for the tradeoff was that Arc is dirty in the right ways.
Axioms first, sugar second. The language is built as a small set of primitives in Scheme with everything else defined in Arc on top of them, in arc.arc. Anyone can read the whole language in an afternoon, and - more to the point - anyone can change it. Arc expects you to extend the language with macros rather than work around it.
No object-orientation. Arc has no classes, no objects and no inheritance, by design. Its answer to polymorphic dispatch is that functions, closures, macros and tables cover the ground that objects usually cover in a web application.
One calling convention for everything. Lists, strings and hash tables are all callable. (xs 3) gets the fourth element of a list, the fourth character of a string, or the value at key 3 in a table. This collapses nth, elt, aref and gethash into function application, and it means a table can be passed anywhere a function is expected.
Key Features
Definitions and macros
| |
def and mac are the workhorses, and aif above is close to Arc’s actual definition - an anaphoric conditional that binds the tested value to it inside the body. Anaphoric macros are a Graham speciality (they date to his 1993 book On Lisp) and Arc uses them everywhere: awhen, aand, afn for a self-referential anonymous function.
w/uniq is the hygiene tool - it binds fresh gensyms so a macro’s temporaries cannot capture the caller’s names:
| |
Bracket lambdas
[... _ ...] is shorthand for a one-argument function whose parameter is _:
| |
This is implemented at the reader level (brackets.scm in the distribution installs the readtable), which is exactly the kind of thing Arc does rather than asking you to type (fn (x) (+ x 1)).
Ssyntax
Arc’s most distinctive syntactic idea is ssyntax - special characters inside symbols that expand into ordinary expressions before evaluation. The expander in ac.scm recognises five:
| Character | Meaning | Example | Expands roughly to |
|---|---|---|---|
: | function composition | (car:cdr xs) | ((compose car cdr) xs) |
~ | complement (negation) of a function | (rem ~even nums) | (rem (complement even) nums) |
. | application | f.x | (f x) |
! | application to a quoted argument | tab!key | (tab 'key) |
& | conjunction of predicates | (keep odd&big xs) | (keep (andf odd big) xs) |
A further character, _ for currying, exists in the source but is commented out - one of several places where the distribution is visibly a working notebook rather than a finished product.
The payoff is code like map:car or pr:string, where the composition costs one character instead of a wrapper form. The cost is that symbols are no longer atomic tokens, which surprises people arriving from other Lisps.
Assignment and places
= is the universal assignment operator, and it works on places rather than just variables:
| |
Arc supplies the whole push/pop/++/zap family on top of the same place machinery.
The web stack
Arc ships a web server and an HTML generation library, and this is where the language’s design goals become visible all at once. The canonical example is Graham’s own answer to the Arc Challenge:
| |
Five lines produce three pages with state carried between them. The trick is that aform and w/link store closures server-side and hand the browser an opaque identifier - continuation-style web programming, implemented in a few dozen lines of ordinary Arc rather than as a language feature. Whether you find this elegant or alarming (those closures live in server memory and expire) is a fair test of whether Arc is for you.
Evolution
| Release | Date | Notes |
|---|---|---|
| arc0 | January 29, 2008 | First public release; requires MzScheme; ASCII only |
| arc1 / arc2 | February 2008 | Rapid iteration driven by Arc Forum feedback; arc2 announced February 25, 2008 |
| arc3 | June 11, 2009 | Follows a public request-for-bugs period in May 2009 |
| arc3.1 | August 4, 2009 | Ported to MzScheme 4.x by Robert Morris with Eli Barzilay; intrasymbol + replaced by & |
| arc3.2 | October 2018 | Current official release; files dated October 9, 2018 |
The gap in that table is the story. Between August 2009 and October 2018 there was no official release at all, and arc3.2 - itself now years old - is still current. The distribution wears its history openly: the how-to-run-news file inside the arc3.2 tarball still instructs you to tar xvf arc3.1.tar.
Two forces filled the vacuum. Anarki, the community fork, took the opposite governance stance to official Arc - commit rights for anyone who asks, no compatibility guarantee - and accumulated the libraries, fixes and newer-Racket support that official Arc never received. And a series of independent implementations appeared: Rainbow on the JVM, Arcadia in C, and various partial ports to other hosts. A language whose entire core is a couple of thousand lines is unusually easy to reimplement, and the number of people who did so says something about how much affection the design attracted even from people who did not use it.
Running Arc Today
Official Arc has no Docker image and no package-manager distribution, which is why the Docker section of this page is empty. Installation is exactly as minimal as the language:
| |
That is the entirety of the official instructions. Because arc3.2 is hosted on Racket and depends on Racket internals - including the FFI trick that restores mutable cons cells - compatibility with any given modern Racket version is worth testing rather than assuming; forum threads over the years record people hitting version-specific breakage. Anarki, which according to its README targets a recent Racket (7.x or later) and is actively maintained, is generally the more reliable route for anyone who actually wants to run Arc code today.
To run Hacker News itself, the distribution’s how-to-run-news file walks through creating an admin file, loading news.arc and calling (nsv) to serve on port 8080. It works. Standing up your own copy of Hacker News from a source file of roughly 2,600 lines remains one of the more startling things you can do with a Lisp on a Tuesday evening.
Current Relevance
Arc is dormant, and it is honest to say so. Official development stopped in any meaningful sense around 2009; the 2018 release was a refresh rather than a direction; Graham’s language design energy went into Bel, published in October 2019 as a specification written in itself rather than a practical implementation. The Arc Forum is still up - still running news.arc - but posts now arrive months apart.
And yet Arc is not dead in the way most abandoned languages are dead, because its flagship application never stopped running. Hacker News serves a large, sustained audience on a codebase written in a language whose official implementation has had one release since 2009. That is a genuinely unusual fact about the industry, and it is the single strongest piece of evidence for Arc’s central claim: that a very small language, wielded by people who know it intimately, can carry real production load.
Why It Matters
Arc is best understood as an argument rather than a tool, and the argument has three parts worth keeping.
Terseness is a real design axis, not laziness. Most language design conversation is about safety, types and tooling. Arc insists on the opposite end - that the friction of expressing an idea matters, and that a language optimised for the moment when you are still figuring out what you are building is a different language from one optimised for a hundred engineers maintaining it. Both are legitimate; the industry mostly only builds the second.
Shipping your own application as the language’s test case is a powerful discipline. Everything in Arc’s web stack exists because Hacker News needed it. The result is a small library with almost no speculative generality in it - a standard almost no other language holds itself to.
Releasing something unfinished has costs you cannot buy back. Arc’s reception in 2008 was shaped almost entirely by the gap between seven years of anticipation and an ASCII-only Lisp with no libraries. The technical criticism about Unicode was correct, and Arc never recovered the audience it lost in that first week. For anyone thinking about how to launch a language, Arc is the canonical case study on both sides of the ledger.
Arc’s direct lineage is short - Graham’s later Bel, the Anarki fork, a handful of reimplementations - and it would be overstating things to trace any mainstream language back to it. What survived instead are its questions: how small can a usable language be, how much can the reader do, what does a language look like when brevity is the objective function rather than a side effect. Arc lost the adoption race decisively. It asked better questions than most languages that won.
Timeline
Notable Uses & Legacy
Hacker News
The news aggregator and discussion forum run by Y Combinator, launched February 19, 2007 and written in Arc by Paul Graham. Its source is distributed with the language itself as news.arc - approximately 2,600 lines of Arc in the arc3.2 release - making Hacker News simultaneously the language's flagship application, its regression test, and the reason anyone outside a Lisp mailing list has heard of Arc.
Arc Forum (arclanguage.org)
The official Arc discussion site is itself an instance of news.arc with cosmetic changes, as Graham noted when releasing arc0 in 2008. It has been running continuously for well over a decade and is the primary archive of Arc release announcements, bug reports and design arguments.
Anarki
A community-managed, deliberately permissive fork of Arc hosted on GitHub, whose stated policy is to give commit privileges to anyone who asks and which is explicitly not constrained to maintain compatibility with official Arc. It carries the libraries, bug fixes and newer Racket support that the official releases never got, and according to its README it targets a recent Racket (7.x or later).
Alternative implementations
Arc's small core made it a popular reimplementation target: Rainbow (a JVM implementation in Java), Arcadia (a C implementation) and assorted partial ports to other host languages have been written by community members. None displaced the official Racket-hosted implementation, but collectively they are evidence of how little language there is to reimplement.