RacketCon 2026 (sixteenth)

Table of Contents

1. Overview

  • Date: October 3–4, 2026
  • Location: Oakstop, Broadway Gallery Suite, Oakland, California
  • URL: https://con.racket-lang.org/
  • Streamed live; recordings on YouTube afterwards.
  • SPLASH/ISSTA 2026 opens in Oakland on the same day.

Written from the published program on 2026-10-01, before the conference. The examples below were run on Racket 8.15 and Guile 3.0.10. Previous edition: RacketCon 2025.

2. Schedule

2.1. Saturday, October 3

Time Speaker Talk
9:00 Pat Hanrahan On Notation (keynote)
10:30 Fred Fu Type Inference With Logical Types For Untyped Languages
11:10 Lucas Myers Language-Oriented Low-Level Programming with Pille
1:30 Mike Delmonaco Treason: Making Macros and IDE Services Work Together
2:10 Pavel Panchekha Herbie: Improving Floating-point Accuracy
3:30 JJ Effect Handlers in cio
4:10 Ryan Culpepper BrandX: Commoditizing OOP with Interfaces, Generics, and Contracts

2.2. Sunday, October 4

Time Speaker Talk
9:00 Sam Phillips Uke: Immutable Dataframes for Racket
9:40 Matthew Flatt A New Foreign-Function Interface: ffi2
11:00 Sam Tobin-Hochstadt The State of Racket
11:30 Racket Management Racket Town Hall

Times are Pacific.

3. How the talks relate

Four threads run through the nine talks, and each has a counterpart at Clojure/conj 2026, held the same week.

Thread RacketCon talks Same question elsewhere
Reaching native code Pille, ffi2 jank on LLVM; babashka's FFI; Panama in Fast, Lean, Native Clojure
Types and checks without a rewrite Type inference, BrandX Clojure 1.13 checked destructuring; a new protocol implementation
Tools that understand macros Treason clojure-lsp and clj-kondo; a source inspector for Hiccup
Control and data as libraries cio, Uke, Herbie core.async; tech.ml.dataset

The keynote sits above all four: notation is what a language-oriented community is arguing about in every one of them.

4. Saturday

4.1. On Notation — Pat Hanrahan

Keynote. Canon Professor Emeritus at Stanford; led the design of RenderMan at Pixar; co-founded Tableau; 2019 Turing Award. No abstract is published.

RenderMan's shading language and Tableau's visual query language are both notations built for one domain, which is the thing Racket exists to make cheap. The same argument, from the other side, opened Clojure/conj's source inspector talk with Bret Victor.

4.2. Type Inference With Logical Types For Untyped Languages — Fred Fu

PhD candidate at Indiana. The problem: a Typed Racket program imports a macro from untyped Racket, the macro expands to a lambda, and nobody can annotate the generated parameters. Local inference does not infer lambda parameters, so the checker rejects the code. His prototype combines occurrence typing with algebraic subtyping.

Occurrence typing is the part to have in mind: the type of a variable narrows after a test on it.

#lang typed/racket
(: describe (-> (U String Integer) String))
(define (describe v)
  (if (string? v)
      (string-append "s:" v)          ; v is a String here
      (number->string (add1 v))))     ; and an Integer here
(describe "a")   ;=> "s:a"
(describe 41)    ;=> "42"
Language The same idea
TypeScript narrowing by typeof and type guards
Kotlin smart casts
Python isinstance narrowing in mypy and pyright
Clojure no static counterpart; core.typed took occurrence typing from Typed Racket

The comparison rows are from memory, not checked.

4.3. Language-Oriented Low-Level Programming with Pille — Lucas Myers

PhD student at Northwestern, advised by Robby Findler. Pille grafts Rhombus's enforestation, the step that turns a flat token stream with infix operators into a tree, onto a new core language with an LLVM-based compiler. The macros stay; the Racket VM goes, and with it the runtime that rules out microcontrollers.

This is the same move as jank, presented at Clojure/conj two days earlier: keep the language's metaprogramming, replace the host with LLVM. jank keeps Clojure's runtime semantics and reaches for C++ interop. Pille gives up the runtime to reach the bottom of the stack.

4.4. Treason: Making Macros and IDE Services Work Together — Mike Delmonaco

Software engineer at AWS. Macros get in the way of IDE services when the program is broken or half-typed, because expansion stops at the first error. Treason's expander recovers and keeps collecting. The stated contribution is spec-driven subexpression expansion: syntax-class annotations say which parts of a macro use are expressions, so they can be expanded even when the macro use around them is broken.

Clojure's answer to the same problem is to not expand at all: clj-kondo and clojure-lsp analyse source statically and need a hint for every unfamiliar macro. Treason takes the opposite bet. He spoke last year on a match-like DSL for deep immutable updates.

4.5. Herbie: Improving Floating-point Accuracy — Pavel Panchekha

Associate Professor at Utah. Two ways of writing the same formula can differ enormously in accuracy; Herbie searches for the accurate one. Ten years of writing it in Racket.

The standard example, run here. Both functions compute √(x+1) − √x:

#lang racket
(define (naive x) (- (sqrt (+ x 1)) (sqrt x)))
(define (rewritten x) (/ 1 (+ (sqrt (+ x 1)) (sqrt x))))
(for ([x '(1e0 1e8 1e16)])
  (printf "~a  naive ~a  rewritten ~a\n" x (naive x) (rewritten x)))
1.0  naive 0.41421356237309515  rewritten 0.4142135623730951
100000000.0  naive 5.000000055588316e-5  rewritten 4.9999999874999996e-5
1e+16  naive 0.0  rewritten 5e-9

At 10^16 the naive form returns zero. The subtraction cancels every significant digit; the rewritten form has no subtraction. Herbie finds that rewrite without being told.

4.6. Effect Handlers in cio — JJ

cio is an untyped effect-handler library for Racket and for Guile. An effect handler separates asking for something from deciding what the answer is, and the handler may resume the asker.

The primitive underneath, in Guile, with no library. The program asks; the handler answers twice:

(define tag (make-prompt-tag "ask"))
(define (ask question) (abort-to-prompt tag question))
(define (program) (+ 1 (ask 'how-many)))

(call-with-prompt tag program
  (lambda (k question) (list question (k 41) (k 99))))
;;=> (how-many 42 100)

k is the rest of program from the point it asked. Calling it twice is what exceptions cannot do.

Language Nearest thing
Racket, Guile delimited continuations: prompts and abort
OCaml 5 effect handlers in the language
Koka, Eff typed effect handlers
Common Lisp the condition system: handlers that resume, via restarts
Clojure none on the JVM; core.async's go rewrites to a state machine instead

The comparison rows are from memory. That the library targets Guile as well as Racket is the reason to watch this one from a Guile project.

4.7. BrandX: Commoditizing OOP with Interfaces, Generics, and Contracts — Ryan Culpepper

Racket developer, macros and library design. A new library for OOP through interfaces and generic functions with proper contract support, motivated by limits in racket/class and racket/generic.

The neighbours are CLOS generic functions and Clojure protocols. Chris Nuernberger's Clojure/conj talk the day before proposed a replacement protocol implementation for Clojure on similar grounds: the built-in one has limits that only show at scale.

5. Sunday

5.1. Uke: Immutable Dataframes for Racket — Sam Phillips

An opinionated dataframe library: immutable, and careful about copying. Racket already has several dataframes.

The Clojure counterpart is tech.ml.dataset, which is columnar and functional-by-default over typed buffers. The question to carry in: what does "efficient about copying" mean without persistent data structures underneath?

5.2. A New Foreign-Function Interface: ffi2 — Matthew Flatt

Racket's FFI (Eli Barzilay, about 2004) is dynamic and convenient. Chez Scheme's ftypes (Andy Keep, about 2011) is static and fast, with compact foreign pointers and cheap checks. ffi2 brings the two together, with small changes to Chez Scheme.

System How it reaches C
Racket ffi/unsafe dynamic, macro-built, no C stub
Chez ftypes static layout known at compile time
Guile (system foreign): dynamic, pointer and bytevector based
Clojure / JVM Panama (java.lang.foreign), final in JDK 22
babashka its own FFI support, used for libsodium in this week's workshop
jank C++ interop in the language, no binding layer

This table is the week's theme in one place: three Lisp communities shipped or showed a new way to call native code within five days.

5.3. The State of Racket, and Town Hall

Sam Tobin-Hochstadt, then questions to Racket management. No abstract.

6. Destructuring maps: Racket has it, Guile does not

Not a talk on this year's program. It is here because Clojure 1.13's map destructuring was the subject of the Clojure/conj keynote this week, and the comparison with Racket turns up a gap in Guile.

Racket's match destructures hash tables, with defaults, a rest binding and an explicit closed mode:

#lang racket
(define order (hash 'id 7 'role 'admin))

(match order [(hash* ['id id] ['name name #:default "anon"] #:rest rest)
              (list id name rest)])
;;=> (7 anon #hash((role . admin)))

(match order [(hash* ['id id] #:closed) id])
;; no match: 'role is present and the pattern is closed

Guile's (ice-9 match) has no hash-table pattern. An association list matches only structurally, so key order matters:

(use-modules (ice-9 match))

(match '((id . 7) (role . admin)) ((('id . id) . rest) (list id rest)))
;;=> (7 ((role . admin)))

(match '((role . admin) (id . 7)) ((('id . id) . rest) id))
;; no match: order matters

(define table (make-hash-table))
(hash-set! table 'id 7)
(match table (_ 'only-wildcard))
;;=> only-wildcard
Feature Clojure 1.13 Racket match Guile (ice-9 match)
Bind by key from a map :keys hash*, hash-table no
Default for an absent key :or #:default no
Absent key is an error :keys! the default: no match no
The unmentioned entries, as data :excess #:rest no
Reject unmentioned entries not offered #:closed no
Absent keys collected as data :missing no no

The Clojure column is from running 1.13.0-alpha8; the Racket and Guile columns are from the runs above. Racket offers the closed mode Clojure declined to. Neither Racket nor Guile reports what was missing as a value.

That gap is a project: a Guile library giving match keyed patterns over hash tables and association lists, with defaults and a rest binding as in Racket, and with the missing-keys-as-data idea from Clojure. It would be a paper for the Scheme Workshop: what each design chose, and which choices survive on a Scheme with mutable hash tables and no persistent maps.

7. Notes

  • TBD, after the stream.