Racket (programming language)
Last reviewed
May 2, 2026
Sources
20 citations
Review status
Source-backed
Revision
v1 ยท 3,427 words
Improve this article
Add missing citations, update stale details, or suggest a clearer explanation.
Last reviewed
May 2, 2026
Sources
20 citations
Review status
Source-backed
Revision
v1 ยท 3,427 words
Add missing citations, update stale details, or suggest a clearer explanation.
Racket is a general-purpose, multi-paradigm programming language in the Lisp family and a direct descendant of Scheme. It is dynamically typed by default, supports first-class functions, continuations, and a hygienic macro system, and is built around an unusual feature for a Lisp: each source file declares its own language with a #lang line at the top, which lets users build and ship their own dialects on top of the same compiler and runtime. Racket is best known for two things. The first is its long career as a teaching language behind the textbook How to Design Programs and the DrRacket IDE used in introductory CS courses at Northeastern, Brown, Waterloo, and elsewhere. The second is its role as a research vehicle for programming language design, where its emphasis on language-oriented programming has produced typed dialects, lazy dialects, solver-aided dialects, and dozens of domain-specific languages.
The project began life in January 1995 at Rice University under Matthias Felleisen as PLT Scheme, named after the Programming Language Team. It was renamed Racket on June 7, 2010, on the same day version 5.0 shipped, to signal that the system had moved well beyond the standard Scheme it started from. Today Racket is developed by a distributed group of researchers and contributors at Northeastern, Utah, Brown, Indiana, Waterloo, and elsewhere, and is released under the MIT and Apache 2.0 licenses.
| Field | Value |
|---|---|
| Paradigms | Multi-paradigm: functional, imperative, object-oriented, logic, meta |
| Family | Lisp / Scheme |
| Typing discipline | Dynamic by default, optional static typing via Typed Racket |
| First appeared | January 1995 (as PLT Scheme) |
| Renamed Racket | June 7, 2010 (with version 5.0) |
| Designed by | Matthias Felleisen and the PLT group |
| Implementation | Racket CS (default since v8.0, built on Chez Scheme) |
| File extensions | .rkt, .rktl, .scrbl |
| License | MIT or Apache 2.0 (dual) |
| Website | racket-lang.org |
Matthias Felleisen founded PLT Inc. in the mid 1990s as a research and pedagogy group focused on novice programmers. In January 1995 the group decided to build a teaching environment around Scheme, and Matthew Flatt put together the first virtual machine, MrEd, by stitching together libscheme, wxWidgets, and a few other free systems. From that base the group, including Flatt, Robby Findler, Shriram Krishnamurthi, and Cormac Flanagan, produced DrScheme, an editor and runtime aimed at students, alongside MzScheme, a command-line implementation with the same core.
The project grew steadily over the next fifteen years. Hygienic macros, the module system, contracts, and the language-level mechanism all arrived during the PLT Scheme era. By the late 2000s the system had drifted far enough from R5RS and R6RS Scheme, and added enough of its own features, that the Scheme name was starting to mislead users. The R6RS standard in particular pushed Scheme in a direction the PLT group did not want to follow, and there was no clean way to keep calling the system Scheme without inviting comparisons that did not really apply.
On June 7, 2010, PLT Scheme was renamed Racket. The release notes for version 5.0 framed the change as a signal that the system had outgrown the Scheme label, and that future development would be done under a name that did not promise standards conformance with a language whose direction the project disagreed with. DrScheme became DrRacket, MzScheme became Racket, and the PLT brand survived in package names and in the team itself.
After the rename, the focus shifted increasingly toward language-oriented programming and toward the macro system as a way of building entire languages, not just libraries. Typed Racket, which had been published in 2008 by Sam Tobin-Hochstadt and Matthias Felleisen, matured into a usable production dialect. New dialects appeared, including Lazy Racket, Hackett, and Rosette, and the #lang mechanism became central to how Racket code was structured.
The original Racket virtual machine, retroactively called Racket BC ("before Chez" or "bytecode"), was a custom JIT-based implementation written largely in C. Starting around 2017 the team, led by Matthew Flatt, began rewriting the runtime on top of Chez Scheme, Kent Dybvig's high-performance Scheme compiler. Cisco had open-sourced Chez Scheme in 2016, which made the move possible.
The rewrite replaced about 200,000 lines of C code with around 150,000 lines of Scheme and Racket code. The new implementation, called Racket CS, became the default in Racket 8.0 on February 13, 2021. Racket BC remained available through a separate installer, mainly to support older code that depended on its FFI quirks. Racket CS ships with better generational and parallel garbage collection, faster startup, and a smaller maintenance burden, since the compiler is written in the same family of languages it compiles.
Racket is a Lisp-1, which means functions and values share a single namespace. This is the same convention as Scheme and Clojure and the opposite of Common Lisp, which keeps separate namespaces for functions and ordinary variables. The Lisp-1 choice makes higher-order programming smoother because the same name f can refer to a function value without funcall or #' ceremony.
Like every Lisp, Racket is homoiconic: programs are written as nested S-expressions, and the same nested-list structure is what macros operate on. A short example:
#lang racket
(define (fact n)
(if (= n 0)
1
(* n (fact (- n 1)))))
(fact 10) ; 3628800
The #lang racket line at the top is the part that does not look like ordinary Scheme. It declares which language to read the rest of the file in. racket is the kitchen-sink dialect with the full standard library; racket/base is a smaller subset; typed/racket adds static types; lazy makes evaluation lazy; scribble/base turns the file into a documentation source. Each #lang is itself a normal Racket module that can be installed via the package system, which means new languages are first-class users of the same tooling as ordinary code.
Racket's macro system extends Scheme's syntax-rules and syntax-case with syntax-parse, a pattern-matching language for syntax that includes integrated error messages and reusable syntax classes. Macros are hygienic by default, meaning identifiers introduced by a macro do not accidentally capture or conflict with identifiers in the surrounding code. This is the same property Scheme made standard with syntax-rules in 1986, but Racket extends it with control over hygiene when you actually need to break it.
The deeper claim Racket makes is that macros are not just for adding little features to an existing language. They are for building entire new languages. A #lang is a module that exports a reader and a set of macros, and the result is that the file under it gets a brand-new surface syntax and semantics. Racket has been used this way to build educational sublanguages (the various Beginning, Intermediate, and Advanced Student Languages used by How to Design Programs), typed dialects, lazy dialects, query languages, build systems, slideware, and book-publishing systems. Matthew Butterick's book Beautiful Racket is a long worked example of building several small languages from scratch using these tools.
A tiny taste of a macro:
#lang racket
(define-syntax-rule (unless test body ...)
(if test (void) (begin body ...)))
(unless (> 1 2)
(displayln "one is not greater than two"))
unless is not a primitive in Racket; this defines it as a one-line macro that expands to an if.
Racket also ships with a contract system, originally designed by Findler and Felleisen, that lets you attach precondition and postcondition checks to functions and modules. Contracts are first-class values and can be combined like other values. When a contract fails, the system blames a specific party (the function or its caller) rather than just printing a stack trace. The contract work fed directly into Typed Racket, since the boundary between typed and untyped modules is implemented as automatically generated contracts.
By default Racket is dynamically typed, with the usual Lisp behavior: any value can be stored in any variable, and type errors show up at runtime. This is the same model as Scheme, Clojure, and other dynamic Lisps.
For code that wants static types, the standard option is Typed Racket, a typed dialect that lives at typed/racket. Typed Racket was introduced by Sam Tobin-Hochstadt and Matthias Felleisen in their 2008 POPL paper The Design and Implementation of Typed Scheme, and it is one of the better-known industrial-strength gradual typing systems. It is designed to be sound across the boundary between typed and untyped modules, with values passed between the two worlds wrapped in dynamically checked contracts.
Typed Racket includes recursive union types, parametric polymorphism, subtyping, and a feature called occurrence typing, which refines a value's type within a branch based on a type predicate. For example:
#lang typed/racket
(: greet (-> (U String #f) String))
(define (greet name)
(if (string? name)
(string-append "hello, " name)
"hello, stranger"))
Inside the if branch, name is narrowed from (U String #f) to String, so string-append typechecks without an explicit cast. The follow-up paper Logical Types for Untyped Languages (Tobin-Hochstadt and Felleisen, 2010) gave the formal account of how this works.
A decade after the original paper, the same authors published Migratory Typing: Ten Years Later (2017), reflecting on what worked and what did not. One recurring finding was that soundness comes at a real cost when typed and untyped code mix heavily, since contract checks at module boundaries can dominate runtime; Is Sound Gradual Typing Dead? (Takikawa et al., POPL 2016) measured this in detail. Subsequent Typed Racket work has focused on reducing those overheads.
Racket today has two implementations that share most of the same surface language:
| Implementation | Status | Notes |
|---|---|---|
| Racket CS | Default since 8.0 (2021) | Built on Chez Scheme; faster, parallel garbage collection, easier to maintain |
| Racket BC | Legacy, available via separate installer | Original C-based VM with custom JIT; kept for compatibility |
Both implementations compile through the same expander, which is itself written in Racket, so a #lang defined in one works in the other. The expander, written by Matthew Flatt and known as the "new" or bootstrapped expander, is one of the larger pieces of Racket-in-Racket and the step that made the Chez migration possible: once the expander was self-hosting, the choice of underlying runtime became swappable.
DrRacket, formerly DrScheme, is the official IDE. It is itself a Racket program. The interface has two panes: a definitions window for editing source, and an interactions window that doubles as a REPL. The IDE understands the #lang line of the open file and switches its behavior accordingly: hitting Run on a #lang typed/racket file gets you the Typed Racket type checker; opening a Beginning Student Language file restricts the available primitives and syntax to the subset matching a given chapter of How to Design Programs.
Features that are unusual for a beginner-focused IDE include a stepper that shows substitution-based reduction one step at a time (used heavily in introductory courses), a graphical syntax-error highlighter that draws arrows from binding to use, integrated check-syntax for tracking variable scope, an algebraic stepper, and tight integration with the macro expander so that you can step through a macro expansion the way you might step through a function call. DrRacket also doubles as a research IDE for the language-design work the PLT group does, since modifications to the expander and reader are visible inside the same environment that students use.
A significant fraction of Racket's user base touches the language through a CS course or a curriculum, not through industry. Two efforts in particular are worth singling out.
How to Design Programs (HtDP), by Matthias Felleisen, Robert Bruce Findler, Matthew Flatt, and Shriram Krishnamurthi, was first published by MIT Press in 2001, with a second edition in 2018 that is freely available online. The book teaches a systematic approach called the design recipe, a six-step process from data definitions through templates to function bodies and tests. It does not use the full Racket language. Instead it uses a sequence of teaching languages (Beginning Student, Beginning Student with List Abbreviations, Intermediate Student, Intermediate with Lambda, Advanced Student) that grow in expressive power as the student progresses. The teaching languages are themselves built using the #lang mechanism. HtDP underlies introductory courses at Northeastern, Brown, the University of Waterloo, the University of British Columbia, and other places.
The Bootstrap curriculum, started by Emmanuel Schanzer in 2005 with Kathi Fisler at WPI and Shriram Krishnamurthi at Brown, takes a similar approach but pushes it down into middle and high schools. Bootstrap:Algebra teaches students to write a small video game while simultaneously covering linear functions, function composition, the Pythagorean theorem, piecewise functions, and other topics from a standard algebra curriculum. The programs are written in a teaching subset of Racket, and the curriculum has been used in over 150 schools in the United States.
The Racket ecosystem is small compared to mainstream languages, but it is reasonably complete. The package manager is invoked through raco, which is the umbrella command-line tool for everything that is not the language proper:
| Command | Purpose |
|---|---|
raco pkg install/update/remove | Package management |
raco make | Ahead-of-time bytecode compilation |
raco exe | Build a standalone executable |
raco doc | Open the local documentation |
raco test | Run a test suite |
raco scribble | Build documentation from Scribble sources |
Packages live in a central catalog at pkgs.racket-lang.org, but a package source can also be a Git repository or a zip file. There is no version pinning beyond what a Git ref or a release file gives you, and the catalog is more of a name-to-source map than a content host.
A non-exhaustive list of well-known Racket projects:
| Project | Author(s) | Description |
|---|---|---|
| Typed Racket | Tobin-Hochstadt, Felleisen, others | Statically typed dialect |
| Rosette | Emina Torlak, Rastislav Bodik | Solver-aided language for synthesis and verification, built on Z3 |
| Hackett | Alexis King | Haskell-like language with Racket macros |
| Pollen | Matthew Butterick | Publishing system used to write Practical Typography and Beautiful Racket |
| Frog | Greg Hendershott | Static blog generator |
| Scribble | PLT | Documentation language used for the Racket reference and HtDP itself |
| Lazy Racket | PLT | Call-by-need variant |
| FrTime | PLT | Functional reactive variant |
Scribble deserves a separate mention. It is the documentation language that the Racket reference, the Racket guide, and a long list of third-party manuals are written in. Pollen is in turn built on Scribble, which is the kind of layered DSL stack that the #lang system is designed to encourage.
Racket sits in the same family as several other Lisps, and the differences are easier to see side by side.
| Feature | Racket | Scheme | Common Lisp | Clojure |
|---|---|---|---|---|
| Namespaces | Lisp-1 | Lisp-1 | Lisp-2 | Lisp-1 |
| Standard size | Large, batteries-included | Small, minimalist | Large, ANSI standard | Medium, hosted on JVM |
| Macro hygiene | Hygienic, with syntax-parse | Hygienic since R5RS | defmacro, not hygienic by default | Mostly hygienic via gensym/#' |
| Typing | Dynamic plus optional static (Typed Racket) | Dynamic | Dynamic, with optional declarations | Dynamic, plus core.typed and Spec |
| Concurrency | Threads, places, futures | Implementation-defined | Implementation-defined | STM-influenced reference types |
| Host platform | Native (Chez) or BC | Many | Many | JVM, JS, .NET via ports |
| Distinctive feature | #lang and language-oriented programming | Minimalism, continuations | Macros and CLOS object system | JVM interop, persistent data structures |
If you already know Scheme, most of Racket will feel familiar, with two big additions: the #lang mechanism and the much larger standard library. If you come from Common Lisp, the absence of CLOS in the same form will feel odd, although Racket has its own object system. If you come from Clojure, the static-typing story is very different (Typed Racket is more sound-by-construction than core.typed) and the host story is the inverse: Racket runs on its own runtime rather than on the JVM.
Racket has been a workhorse for programming language research, especially around macros, gradual typing, and contracts. The volume of POPL, ICFP, and PLDI papers using Racket as either object of study or implementation vehicle is large, and several techniques that are now common in mainstream languages, like sound gradual typing and structural contracts, were prototyped in Racket first.
The relevance to AI is mostly indirect, through two channels. The first is program synthesis and formal verification, both of which connect to the idea of generating or checking programs against specifications, which is also what large language model code assistants try to do, just by very different means. Rosette, designed by Emina Torlak and Rastislav Bodik and described in the 2013 Onward! paper Growing Solver-Aided Languages with Rosette, is a Racket-based language that compiles programs to logical constraints solved by SMT solvers like Z3. Rosette has been used to build verifiers and synthesizers for new languages by writing an interpreter and letting the solver do the heavy lifting, which complements LLM-based program generation rather than competing with it. Sketch, designed by Armando Solar-Lezama, is the original syntax-guided synthesis system; while Sketch itself is not in Racket, the synthesis-by-sketching idea has been re-implemented and extended in Rosette.
The second channel is education. A non-trivial fraction of programming language researchers, including some who work on formal methods, type theory, and synthesis at AI-adjacent labs, learned to think about programs through How to Design Programs. The design-recipe approach, the emphasis on data definitions and templates, and the use of contracts to specify behavior are all habits that show up in research code regardless of the language it ends up in.
This influence is real but easy to overstate. Racket is not a meaningful target for industrial machine-learning workloads, has no GPU story to speak of, and is not on the shortlist of languages that LLM code assistants are tuned for. Its place in an AI Wiki is as a notable Lisp dialect with a serious teaching tradition and a research community that overlaps with the formal-methods side of computer science.
Racket has not been a fixture of mainstream commercial software, but it has been used in several visible places. In academia, Racket is used in production in courses at Northeastern (Felleisen's group), Brown (Krishnamurthi), the University of Utah (Flatt), Indiana University (Tobin-Hochstadt), the University of Waterloo, and Worcester Polytechnic Institute (Fisler), among others. Pollen, the publishing system, has been used to produce several professionally typeset books, including Matthew Butterick's Practical Typography and Typography for Lawyers. The Racket reference manual itself is one of the longest documents written in Scribble.