Est. 2008 Advanced

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

Paradigm Multi-paradigm within the Lisp tradition: primarily functional, with heavy use of macros and metaprogramming, plus unrestricted mutation and imperative control flow. Deliberately not object-oriented - Graham has argued that object-orientation is unnecessary in a language with sufficiently good functions and macros
Typing Dynamic and latent. Values carry a type queried with (type x) - cons, sym, fn, table, string, char, int, num - and there are no type declarations or annotations anywhere in the language
First Appeared 2008 (announced in 2001; first public release, arc0, on January 29, 2008)
Latest Version arc3.2, released October 2018 (source files in the official tarball are dated October 9, 2018)

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

1
2
3
4
5
6
7
(def fib (n)
  (if (< n 2) n
      (+ (fib (- n 1)) (fib (- n 2)))))

(mac aif (expr . body)
  `(let it ,expr
     (if it ,@body)))

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:

1
2
3
(mac swap (x y)
  (w/uniq tmp
    `(let ,tmp ,x (= ,x ,y) (= ,y ,tmp))))

Bracket lambdas

[... _ ...] is shorthand for a one-argument function whose parameter is _:

1
(map [+ _ 1] '(1 2 3))     ; => (2 3 4)

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:

CharacterMeaningExampleExpands roughly to
:function composition(car:cdr xs)((compose car cdr) xs)
~complement (negation) of a function(rem ~even nums)(rem (complement even) nums)
.applicationf.x(f x)
!application to a quoted argumenttab!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:

1
2
3
(= x 10)
(= (car xs) 'first)
(= tab!key "value")

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:

1
2
3
4
(defop said req
  (aform [onlink "click here" (pr "you said: " (arg _ "foo"))]
    (input "foo")
    (submit)))

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

ReleaseDateNotes
arc0January 29, 2008First public release; requires MzScheme; ASCII only
arc1 / arc2February 2008Rapid iteration driven by Arc Forum feedback; arc2 announced February 25, 2008
arc3June 11, 2009Follows a public request-for-bugs period in May 2009
arc3.1August 4, 2009Ported to MzScheme 4.x by Robert Morris with Eli Barzilay; intrasymbol + replaced by &
arc3.2October 2018Current 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:

1
2
3
4
5
6
7
8
# 1. Install Racket from https://racket-lang.org
# 2. Fetch and unpack the official release
curl -O http://www.arclanguage.org/arc3.2.tar
tar xf arc3.2.tar
cd arc3.2

# 3. Start the REPL
racket -f as.scm

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

2001
Paul Graham announces that he is working on a new dialect of Lisp named Arc, and over the following years publishes essays sketching its goals - most explicitly Being Popular (May 2001), which argues that a language wins by being terse, hackable and available for free to the people who write the interesting programs
2007
Hacker News launches on February 19, 2007 under the name Startup News, written in Arc by Graham at Y Combinator, and is renamed Hacker News later that year. The language is at this point still unreleased - the site is the first substantial Arc program and doubles as the language's test case
2008
The first public release, arc0, appears on January 29, 2008, accompanied by the essay Arc's Out and the arclanguage.org site and forum. Graham states plainly that Arc supports only ASCII, that it is aimed at experienced Lisp programmers, and that it is meant to be dirty in the right ways rather than polished
2008
In February 2008 Graham publishes The Arc Challenge, a small web-application task - input field, then a click here link, then a page echoing what the user typed - used to compare the code-tree size of solutions across languages. The Arc answer is a single five-line defop, and the essay becomes the most widely circulated demonstration of what the language is for
2008
arc2 is announced on the Arc Forum by Graham on February 25, 2008, less than a month after the initial release - the beginning of a short, intense period of language churn driven directly by forum feedback
2009
Graham posts Arc3 now the current release on June 11, 2009, following a public request-for-bugs period on the forum in May 2009 and a string of small feature posts through June
2009
arc3.1 is announced on August 4, 2009. With help from Racket developer Eli Barzilay, Robert Morris gets Arc running on the then-current MzScheme 4.x, which had made cons cells immutable; the workaround pokes at the underlying pointers through Racket's FFI. Graham reports that Hacker News had been running the new version for about a week and seemed a bit faster, maybe 10-20% - an informal production observation on one site's workload, not a benchmark
2009
Graham's activity on the Arc Forum tapers off through late 2009, with his last release-related posts there dating from that year. Official development effectively goes quiet while Hacker News, still written in Arc, keeps growing
2018
arc3.2 is released in October 2018 (the files in the official tarball are dated October 9, 2018) - the first official release in over nine years, and still the current one. It ships arc.arc, the Racket-hosted compiler ac.scm, the web server, and news.arc, the Hacker News source
2019
In October 2019 Graham publishes Bel, a specification for a different Lisp dialect written in itself. Bel is not a successor implementation to Arc - it is a far more theoretical exercise - but its appearance confirms that Graham's language design attention had moved elsewhere
2026
arclanguage.org and its forum - themselves running news.arc, the same code as Hacker News - remain online as of July 2026, though traffic is reportedly thin, with new forum submissions arriving months apart. The community fork Anarki continues to receive commits on GitHub

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.

Language Influence

Influenced By

Influenced

Bel

Running Today

Run examples using the official Docker image:

docker pull
Last updated: