RacketCon 2026 (sixteenth)
Table of Contents
- 1. Overview
- 2. Recordings
- 3. Schedule
- 4. How the talks relate
- 5. Saturday
- 5.1. On Notation — Pat Hanrahan
- 5.2. Type Inference With Logical Types For Rhombus — Fred Fu
- 5.3. Language-Oriented Low-Level Programming with Pille — Lucas Myers
- 5.4. Treason: Making Macros and IDE Services Work Together — Mike Delmonaco
- 5.5. Herbie: Improving Floating-point Accuracy — Pavel Panchekha
- 5.6. Effect Handlers in cio — JJ
- 5.7. BrandX: Commoditizing OOP with Interfaces, Generics, and Contracts — Ryan Culpepper
- 6. Sunday
- 7. Study: the program mapped, and one talk built
- 7.1. Step 1: the program mapped
- 7.2. Reading list by talk
- 7.2.1. Pat Hanrahan, On Notation (Sat 9:00)
- 7.2.2. Fred Fu, type inference (Sat 10:30)
- 7.2.3. Lucas Myers, Pille (Sat 11:10)
- 7.2.4. Mike Delmonaco, Treason (Sat 1:30)
- 7.2.5. Pavel Panchekha, Herbie (Sat 2:10)
- 7.2.6. JJ, cio (Sat 3:30)
- 7.2.7. Ryan Culpepper, BrandX (Sat 4:10)
- 7.2.8. Sam Phillips, Uke (Sun 9:00)
- 7.2.9. Matthew Flatt, ffi2 (Sun 9:40)
- 7.2.10. Sam Tobin-Hochstadt, The State of Racket (Sun 11:00)
- 7.3. Step 2: Treason, built and run
- 8. Destructuring maps: Racket has it, Guile does not
- 9. Related research on this site
- 10. Notes
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, see 2.
- 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. Recordings
The Racket channel's playlist (sixteenth RacketCon) 2026 holds all eleven talks on the program, uploaded 2026-10-07. Each talk below links its own video; titles on YouTube match the program.
| Talk | Video |
|---|---|
| On Notation | 1:10:12 |
| Type Inference With Logical Types For Rhombus | 35:45 |
| Language-Oriented Low-Level Programming with Pille | 36:30 |
| Treason | 33:20 |
| Herbie | 48:28 |
| Effect Handlers in cio | 34:14 |
| BrandX | 45:51 |
| A New Foreign-Function Interface: ffi2 | 38:02 |
| Uke: Immutable Dataframes for Racket | 41:10 |
| The State of Racket | 37:47 |
| Racket Town Hall | 28:14 |
3. Schedule
3.1. Saturday, October 3
| Time | Speaker | Talk |
|---|---|---|
| 9:00 | Pat Hanrahan | On Notation (keynote) |
| 10:30 | Fred Fu | Type Inference With Logical Types For Rhombus |
| 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 |
3.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.
4. 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.
5. Saturday
5.1. On Notation — Pat Hanrahan
Video: YouTube.
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.
5.1.1. Prior art: Fortress, a language that set out to look like mathematics
The Fortress Language Specification, Version 1.0 α (Sun Microsystems, September 19, 2006; 411 pages) is the most deliberate attempt at mathematical notation in a general-purpose language. Its authors are Eric Allen, David Chase, Joe Hallett, Victor Luchangco, Jan-Willem Maessen, Sukyoung Ryu, Guy L. Steele Jr. and Sam Tobin-Hochstadt, who gives the State of Racket on Sunday.
Four ideas from the spec, quoted from sections 2.4, 2.12, 2.13 and 16.7:
- Rendering
- programs are typed in ASCII and displayed as mathematics.
f(x) = x^2 + sin x - cos 2 xrenders with a superscript and italics;a[i]renders as a subscript. Unicode can be typed by name:GREEK_CAPITAL_LETTER_LAMBDAbecomes Λ,lambdabecomes λ,SUMbecomes Σ,CUPbecomes ∪. - Comprehensions
- set-builder notation, computed in parallel by default:
{x/2 | x ← t},{x + y | x ← s, y ← t},{x | x ← t, x ≥ 0}. - Big operators
factorial(n) = PRODUCT[i <- 1:n] i, rendered as a capital pi overi ← 1:n.- Juxtaposition
2 xis multiplication andsin xis application. Which one depends on types and whitespace, so the parser holds a run of juxtaposed terms "in abeyance", type-checks each element, and only then rewrites it into a tree. The spec gives the case it forbids: ifnis both a functional method and a local,nais a static error.
That last rule is the cost of mathematical notation stated plainly: the grammar cannot be parsed without the types.
5.1.2. More examples from the Fortress spec
Quoted from chapter 2 of the spec. The text was extracted from the PDF, which
loses the rendering, so superscripts are restored here by hand and the
blackboard-bold types are written as ℝ and ℤ.
Juxtaposition is multiplication, and a function next to its argument is a call (section 2.6):
factorial(n) =
if n = 0 then 1
else n factorial(n − 1) end
sin x
Comparisons chain as on paper, and parameters take defaults by keyword (2.6.1):
makeColor(red: ℤ64 = 0, green: ℤ64 = 0, blue: ℤ64 = 0) =
if 0 ≤ red ≤ 255 ∧ 0 ≤ green ≤ 255 ∧ 0 ≤ blue ≤ 255
then Color(red, green, blue)
else throw Error end
makeColor(green = 255)
Contracts sit in the function header, before the body; result is bound in
ensures (2.6.4):
factorial(n)
requires n ≥ 0
ensures result ≥ 0
= if n = 0 then 1
else n factorial(n − 1) end
Loops are parallel unless asked otherwise, so this may print in any order
(2.8), and atomic is how parallel code shares state (2.9):
for i ← 1:10 do
print(i " ")
end
-- possible output: 5 4 6 3 7 2 9 10 1 8
atomic do
x += 1
y += 1
end
Units and dimensions are part of the type, checked statically (2.10):
kineticEnergy(m: ℝ kg, v: ℝ m/s): ℝ kg m²/s² = (m v²)/2 v: ℝ m/s = (3 meters + 4 meters)/5 seconds -- fine v: ℝ m/s = (3 meters + 4 seconds)/5 seconds -- static error: meters + seconds v: ℝ m/s = (3 meters + 4 meters)/5 -- static error: m is not m/s kineticEnergy(3.14 kg, 32 f/s in m/s) -- unit conversion
Tests range over a finite collection; properties quantify over a type (2.14):
test factorialResultLarger[x ← 0:100] = x ≤ factorial(x) property factorialResultAlwaysLarger = ∀(x: ℤ) (x ≤ factorial(x))
Where each idea went afterwards:
| Fortress, 2006 | Where it lives now |
|---|---|
requires / ensures |
Racket contracts; Saturday's BrandX talk is about contracts on interfaces |
property ∀(x: ℤ) |
property-based testing: QuickCheck, test.check, rackcheck (Treason uses it) |
| units in the type | F# units of measure; libraries elsewhere |
parallel for by default |
not adopted by any mainstream language; Clojure's pmap and Racket's futures are opt-in |
| type-directed juxtaposition | nowhere; Haskell and Rhombus both chose a grammar that parses without types |
The "where it lives now" column is from memory, except that Treason depends on
rackcheck, which its info.rkt shows.
Sam Tobin-Hochstadt is on the spec's author list, gives the State of Racket on Sunday, and works on Typed Racket. A question in the keynote that brought up Fortress would have had one of its authors in the room. Fortress's two hardest problems, type-directed parsing and parallel-by-default evaluation, are the two Racket never took on; its contracts and its typed treatment of an untyped notation are both things Racket did take on.
5.1.3. The same notation, where it survived: Haskell and Racket
Haskell kept most of it without the type-directed parsing: comprehensions are set-builder notation, and operators can be Unicode with declared fixity, so ∩ binds tighter than ∪ as it does on paper. Run on GHC 9.14.1:
{-# LANGUAGE UnicodeSyntax #-}
import Data.List (union, intersect)
infixl 6 ∪
infixl 7 ∩
(∪), (∩) :: Eq a => [a] -> [a] -> [a]
(∪) = union
(∩) = intersect
infix 4 ∈
(∈) :: Eq a => a -> [a] -> Bool
(∈) = elem
halves t = [x / 2 | x <- t] -- {x/2 | x ← t}
sums s t = [x + y | x <- s, y <- t] -- {x + y | x ← s, y ← t}
nonNegative t = [x | x <- t, x >= 0] -- {x | x ← t, x ≥ 0}
factorial n = product [i | i <- [1 .. n]] -- PRODUCT[i <- 1:n] i
-- halves [2, 4, 6] => [1.0,2.0,3.0]
-- sums [1, 2] [10, 20] => [11,21,12,22]
-- nonNegative [-1, 0, 3] => [0,3]
-- factorial 10 => 3628800
-- [1, 2, 3] ∪ [3, 4] ∩ [4, 5] => [1,2,3,4] (∩ first)
-- 3 ∈ [1, 2, 3] ∪ [4] => True
What Haskell gave up is juxtaposition as multiplication: 2 x is
application of 2. That single choice is what lets it parse without types.
Racket keeps prefix notation and puts the same ideas in named forms. Run on Racket 8.15:
(for/list ([x (list 2 4 6)]) (/ x 2)) ; => (1 2 3)
(for*/list ([x (list 1 2)] [y (list 10 20)]) (+ x y)) ; => (11 21 12 22)
(for/product ([i (in-range 1 11)]) i) ; => 3628800, Π
(for/sum ([i (in-range 1 11)]) (* i i)) ; => 385, Σ
| Idea | Fortress (2006) | Haskell | Racket |
|---|---|---|---|
| Set-builder comprehension | braces, ← generators |
brackets, <- generators |
for/list |
| Big operators | SUM, PRODUCT as Σ, Π |
sum, product over a list |
for/sum, for/product |
| Unicode operators | typed by name, rendered | yes, with declared fixity | any identifier; prefix only |
| Juxtaposition | multiplication or call, by type | always application | none; parentheses |
| Infix | yes | yes | not in Racket; yes in Rhombus |
Rhombus is where Racket's answer moved: infix operators with declared precedence over the same macro system, and the enforestation step that Pille reuses on Saturday afternoon.
Questions to bring to the keynote: does notation belong in the language, in the renderer, or in the editor? Fortress put it in all three. Tableau, which Hanrahan co-founded, put it in the interface and kept the user away from syntax altogether.
5.2. Type Inference With Logical Types For Rhombus — Fred Fu
Video: YouTube.
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.
5.3. Language-Oriented Low-Level Programming with Pille — Lucas Myers
Video: YouTube.
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.
5.4. Treason: Making Macros and IDE Services Work Together — Mike Delmonaco
Video: YouTube.
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.
5.5. Herbie: Improving Floating-point Accuracy — Pavel Panchekha
Video: YouTube.
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.
5.6. Effect Handlers in cio — JJ
Video: YouTube.
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.
5.7. BrandX: Commoditizing OOP with Interfaces, Generics, and Contracts — Ryan Culpepper
Video: YouTube.
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.
6. Sunday
6.1. Uke: Immutable Dataframes for Racket — Sam Phillips
Video: YouTube.
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?
6.2. A New Foreign-Function Interface: ffi2 — Matthew Flatt
Video: YouTube.
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.
6.3. The State of Racket, and Town Hall
Video: The State of Racket; Racket Town Hall.
Sam Tobin-Hochstadt, then questions to Racket management. No abstract.
7. Study: the program mapped, and one talk built
Done on 2026-10-03, the first day of the conference, in two steps: survey the program, then clone one talk's code and run it. The live stream is on BoxCast.
7.1. Step 1: the program mapped
Each link is marked by how it was checked: opened (fetched and read), API (the GitHub or Codeberg API returned the repository), or search (seen only in search results). "Built on" papers are a reasonable lineage picked by topic unless marked as cited by the project itself.
| Speaker | Handle | Code for the talk | Built on |
|---|---|---|---|
| Pat Hanrahan (Stanford) | phanrahan (API; probably his, not confirmed by an official link) | none; a keynote | Iverson, Notation as a Tool of Thought, CACM 1980 (search). His own: RenderMan shading language, SIGGRAPH 1990; VizQL, SIGMOD 2006; Terra, PLDI 2013 (search) |
| Fred Fu (Indiana) | capfredf (API) | none of its own; Typed Racket is racket/typed-racket | Tobin-Hochstadt and Felleisen, Logical Types for Untyped Languages, ICFP 2010; Dolan and Mycroft, MLsub, POPL 2017; Parreaux, The Simple Essence of Algebraic Subtyping, ICFP 2020 (search). His own, as Yuquan Fu: Type Checking Extracted Methods, Programming 2022 (opened) |
| Lucas Myers (Northwestern) | distractedlambda (API) | distractedlambda/pille (API; README says not on the package catalog) | Rafkind and Flatt, Honu, GPCE 2012; Flatt et al., Rhombus, OOPSLA 2023 (search) |
| Mike Delmonaco (AWS) | quasarbright (API) | quasarbright/treason, cloned and built below; editor client treason-vscode (API) | Culpepper and Felleisen, Fortifying Macros, ICFP 2010; Ballantyne, Gamburg and Hemann, ICFP 2024 (syntax-spec) (search). He is the second-largest contributor to syntax-spec (API) |
| Pavel Panchekha (Utah) | pavpanchekha (API) | herbie-fp/herbie (API); package herbie (catalog, opened) |
Herbie's own paper list has 22 entries (opened), starting with Panchekha et al., PLDI 2015. The only talk on the program with its own papers |
| JJ (Vancouver) | Codeberg apropos (API) | codeberg.org/apropos/cio (API); not on GitHub, not in the Racket catalog | Cited by the cio README: Effekt's Effects as Capabilities, OOPSLA 2020, and two follow-ups (opened README) |
| Ryan Culpepper | rmculpepper (API) | rmculpepper/racket-brandx (API); packages brandx, brandx-lib (catalog, opened) |
Flatt, Findler and Felleisen, Scheme with Classes, Mixins, and Traits, APLAS 2006 (search) |
| Sam Phillips | samdphillips (API) | samdphillips/uke (API; Apache-2.0); packages uke, uke-lib and two more (catalog, opened) |
none cited by the project |
| Matthew Flatt (Utah) | mflatt (API) | no repository of its own: pkgs/ffi2 and pkgs/ffi2-lib inside racket/racket (API) |
Barzilay and Orlovsky, Foreign Interface for PLT Scheme, Scheme Workshop 2004 (opened, in the Racket docs bibliography); Keep and Dybvig, Ftypes, Scheme Workshop 2011 (search) |
| Sam Tobin-Hochstadt (Indiana) | samth (API) | none; a state-of-the-project talk | Felleisen et al., A Programmable Programming Language, CACM 2018 (search) |
Seven talks have public code: Pille, Treason, Herbie, cio, BrandX, Uke and ffi2. Hanrahan, Fu and Tobin-Hochstadt do not.
Things a search gets wrong here:
- The conference site gives Fred Fu's title as Type Inference With Logical Types For Rhombus; an earlier copy of the program said "For Untyped Languages". His papers are published as Yuquan Fu.
- cio is on Codeberg. A GitHub user named
aproposalso exists and is not the same person. - ffi2 has no repository of its own.
- Herbie's catalog entry still points at
uwplse/herbie, which redirects toherbie-fp/herbie.
To study each talk:
git clone https://github.com/distractedlambda/pille.git # Pille; needs LLVM, largest build
git clone https://github.com/quasarbright/treason.git # Treason
git clone https://github.com/herbie-fp/herbie.git # Herbie
git clone https://codeberg.org/apropos/cio.git # cio; Racket and Guile
git clone https://github.com/rmculpepper/racket-brandx.git # BrandX
git clone https://github.com/samdphillips/uke.git # Uke; smallest build
git clone --filter=blob:none --sparse https://github.com/racket/racket.git \
&& git -C racket sparse-checkout set pkgs/ffi2 pkgs/ffi2-lib # ffi2
7.2. Reading list by talk
A second, wider survey: five research agents, two speakers each, collecting homepages, repositories, related papers and earlier talks. Every link below was requested on 2026-10-03. 66 of 71 returned 200. Four ACM DOIs redirect to the ACM Digital Library, which refuses scripted requests; they are kept. gnu.org did not answer from this machine, so the Guile manual link is unchecked.
Where it differs from the table above: it found Ryan Culpepper's affiliation (Czech Technical University in Prague), a second paper by Fred Fu from September 2026, Pavel Panchekha's sabbatical at NVIDIA, and a second cio repository. It also settles egg's venue as POPL 2021.
7.2.1. Pat Hanrahan, On Notation (Sat 9:00)
Emeritus professor at Stanford (profile). The program has no abstract, and no earlier talk with this title turned up.
- His language papers
- the RenderMan shading language (SIGGRAPH 1990); Brook for GPUs (2004); Polaris (TVCG 2002), the visualization specification language that led to Tableau's VizQL; Terra (PLDI 2013).
- Related talks
- shading languages (SFU 2023); Hardware as Software (Lambda Days 2021); an NSF lecture transcript arguing for DSLs with precise semantics.
- Probable background
- Iverson, Notation as a Tool of Thought (1979 Turing Lecture).
7.2.2. Fred Fu, type inference (Sat 10:30)
GitHub capfredf; 144 commits in Typed Racket. The inference prototype has no public repository.
- His papers, as Yuquan Fu (Indiana, with Tobin-Hochstadt)
- Type Checking Extracted Methods (‹Programming› 2022); Revisiting Soundness for Occurrence Typing, Semantically (arXiv, September 2026, with Carlo Angiuli), which finds flaws in earlier soundness proofs for occurrence typing and replaces them with a step-indexed logical-relations proof mechanized in Lean.
- Same person?
- no page says Fred Fu and Yuquan Fu are one person. The evidence is a 2020 capfredf commit on the 2022 paper's topic.
- Prior work
- the title extends Logical Types for Untyped Languages (ICFP 2010). Algebraic subtyping: MLsub (POPL 2017, code), Dolan's thesis, and Simple-sub (ICFP 2020, code). Castagna et al., Revisiting Occurrence Typing, which formulates occurrence typing with semantic subtyping.
7.2.3. Lucas Myers, Pille (Sat 11:10)
GitHub distractedlambda. distractedlambda/pille holds four Racket packages: the implementation, Rhombus bindings to the LLVM C API (including the ORC JIT), SPMD "varying" types, and the docs and tests. Last commit 2026-10-02. The Rhombus v1.0 announcement lists Pille as a language built on Rhombus.
- Prior work
- Rhombus (OOPSLA 2023); Honu (GPCE 2012), which introduced enforestation; Terra, an LLVM-compiled low-level language staged from Lua, co-authored by Hanrahan; the enforest docs.
7.2.4. Mike Delmonaco, Treason (Sat 1:30)
GitHub quasarbright; blog; 184 commits in syntax-spec. Built and run in Step 2 below.
- Prior work
- syntax-spec (ICFP 2024); Fortifying Macros (ICFP 2010); Lean 4's Beyond Notations.
- Compared against in the talk
- racket-langserver and rust-analyzer.
7.2.5. Pavel Panchekha, Herbie (Sat 2:10)
University of Utah, on sabbatical at NVIDIA (homepage).
- Code
- herbie-fp/herbie (site), a Racket core with a Rust e-graph component; Rival for interval arithmetic; Odyssey, an interactive interface; FPBench, the benchmark suite.
- Papers
- Herbie (PLDI 2015); egg (POPL 2021); Combining Precision Tuning and Rewriting (ARITH 2021); Rival (ARITH 2023); equality saturation (POPL 2009).
- Talks
- PLDI 2015; NSV 2020.
7.2.6. JJ, cio (Sat 3:30)
Codeberg apropos; site toki.la. apropos/cio implements effect handlers for
Racket and Guile on prompts; its core forms are define-effect,
raise-effect, try, resume and with-effect-handler, and the README
names Effekt as the main model. A second repository,
racket-guile-control, reimplements Guile's delimited-control primitives in
Racket.
- Prior work
- Effekt and Effects as Capabilities; Plotkin and Pretnar, Handling Algebraic Effects; Racket delimited control (ICFP 2007); Guile prompts.
- Other Racket effect libraries
- effect-racket, effection.
7.2.7. Ryan Culpepper, BrandX (Sat 4:10)
Czech Technical University in Prague (profile).
- Code and docs
- rmculpepper/racket-brandx; the docs cover interfaces, generics, bundles, signatures and dependent contracts; the August 2026 announcement gives the motivation. He is testing it by porting his crypto library.
- Prior work
- his own Fortifying Macros and Debugging Hygienic Macros; racket/generic; Classes, Mixins, and Traits (APLAS 2006); Contracts for First-Class Classes; Units, the model for BrandX's bundles and signatures.
- Earlier talk
- Making low-level libraries Rackety (RacketCon 2011 slides).
7.2.8. Sam Phillips, Uke (Sun 9:00)
GitHub samdphillips. samdphillips/uke (docs) has dataframe, column, index and store layers; select, group and left-join return new values instead of mutating.
- Comparable Racket libraries
- data-frame, sawzall, tabular-asa.
- Background
- Towards Scalable Dataframe Systems (VLDB 2020).
7.2.9. Matthew Flatt, ffi2 (Sun 9:40)
University of Utah (homepage).
- Code and docs
- the ffi2 docs; the package ffi2-lib, whose source is in
racket/racket starting at commit
6927f16(authored 2026-03-13). Two earlier commits change Chez Scheme: one adds__errnoand__allocforeign conventions, one adds nongenerativedefine-ftype. The v9.2 notes mention ffi2; Rhombus's ffi library is built on it. - Prior work
- Barzilay and Orlovsky, Foreign Interface for PLT Scheme (Scheme Workshop 2004); Ftypes (2011); Rebuilding Racket on Chez Scheme (ICFP 2019).
7.2.10. Sam Tobin-Hochstadt, The State of Racket (Sun 11:00)
Indiana University (homepage); the most commits in Typed Racket. Also a co-author of the Fortress specification, see the keynote section.
- Earlier State of Racket talks
- 2023, 2024, 2025.
- Releases since RacketCon 2025
- Racket v9.0 (parallel threads); v9.1 (February 2026); v9.2 (ffi2); v9.3 (Markdown docs, faster Check Syntax); Rhombus v1.0 (June 2026, the first stable release) and v1.1.
- His Typed Racket papers
- Typed Scheme (POPL 2008); Logical Types (under Fu above); Occurrence Typing Modulo Theories (PLDI 2016).
The machine these notes were written on runs Racket 8.15, three releases behind v9.3.
7.3. Step 2: Treason, built and run
Treason at commit f901eee (2026-09-30), MIT licensed. It provides
#lang treason and a treason-language-server executable; the editor client
handles .tsn files. Run on Racket 8.15 CS, macOS.
7.3.1. Install and test
git clone https://github.com/quasarbright/treason && cd treason
raco pkg install --auto --batch # 16 s; installs rackcheck as a dependency
raco test reader-tests.rkt lang-tests.rkt lsp-tests.rkt
reader-tests.rkt 20 tests passed lang-tests.rkt 31 tests passed lsp-tests.rkt 173 tests passed
The install also places treason-language-server in Racket's user bin
directory.
7.3.2. A broken macro use
A one-clause macro whose right-hand side and body are annotated as expressions:
#lang treason
(define-syntax my-let
(syntax-rules () [(_ x rhs:expr body:expr) (let ([x rhs]) body)]))
(define total 10)
(my-let n (+ total 1) (* n 2))
Run with racket good.tsn, it prints 22. Then drop the body from the
macro use and add an unrelated error:
#lang treason
(define-syntax my-let
(syntax-rules () [(_ x rhs:expr body:expr) (let ([x rhs]) body)]))
(define total 10)
(my-let n (+ total 1))
(define also-bad unbound-name)
$ racket broken.tsn treason: 2 errors 5:1: my-let: no pattern matched 6:18: unbound-name: unbound identifier
Both errors at once. Racket's expander would stop at the first.
7.3.3. What still answers inside the broken use
The language server can be driven in-process, the way the project's own
lsp-tests.rkt does: open the document through server% and send it LSP
requests. Three queries on total inside the my-let use, against three
versions of the program. Positions are zero-based, counted from the line
after #lang.
well-formed use, annotated (rhs:expr body:expr)
goto-definition on `total` inside the use => definition at line 2, chars 8-13
find-references on the definition => the use at line 3, chars 13-18
autocomplete at `total` inside the use => ("my-let" "total")
broken use (body missing), annotated
diagnostic: unbound-name: unbound identifier
diagnostic: my-let: no pattern matched
goto-definition on `total` inside the use => definition at line 2, chars 8-13
find-references on the definition => the use at line 3, chars 13-18
autocomplete at `total` inside the use => ("also-bad" "my-let" "total")
broken use (body missing), NOT annotated (rhs body)
diagnostic: my-let: no pattern matched
diagnostic: unbound-name: unbound identifier
goto-definition on `total` inside the use => ()
find-references on the definition => ()
autocomplete at `total` inside the use => ()
With the annotations, all three services work inside a macro use that matched no clause. Without them, all three go silent. The annotation is the whole difference, which is the talk's claim.
7.3.4. How it decides what to expand
All in expander.rkt:
- Lines 39–40 and 724–781
(~var x expr)and its shorthandx:exprare a pattern form thatsyntax-rulesdoes not have.annotated-pvaris a match expander that recognises both.- Lines 993–1018,
match-pattern - an annotated pattern variable always
matches, binds like an ordinary one, and also records the syntax it matched
in the result's
ose-stxslist (oseis optimistic subexpression expansion). An unknown syntax class binds but records nothing. A plain pattern variable records nothing. - Line 1056 onward
- on a pair, the matcher recurses into both sides even when the first fails, so every annotated subexpression in the use is collected, not only those before the failure.
- Lines 919–953,
try-patterns - if no clause matches, it ranks clauses by
how far matching got (
progress<?, lines 956–979), keeps the clauses tied for furthest, and takes the intersection of their annotated subexpressions. It raises anose-errorcarrying those subexpressions. - Line 396
- in an expression context the catcher expands them at once, because every binding is already known.
- Lines 570–600
- in a definition context they are held until pass 2, when every binding in the context is known, and expanded then.
So the decision is: expand only what the macro's author marked as an
expression, from the clause or clauses that got furthest, and only once the
scope is complete. The talk script (racketcon/script.md, line 138) names
the failure mode: if an argument is missing, positions shift and the matcher
may treat the wrong subform as the expression.
7.3.5. Relation to syntax/parse and syntax-spec
- syntax/parse (Culpepper and Felleisen, Fortifying Macros, ICFP 2010)
the
x:exprnotation is syntax/parse's syntax-class annotation. In syntax/parse the class drives error messages; in Treason it also tells the expander which subforms are expressions it can expand on its own. The talk script (line- says you have to annotate the same way in syntax/parse to get good
errors.
- syntax-spec (Ballantyne, Gamburg and Hemann, ICFP 2024)
- Treason only knows
one syntax class,
expr. The talk ends (script, lines 152–170) on syntax-spec as the way to say more: a grammar for the macro's own nonterminals, such as patterns, and its binding rules, which would let the same recovery work inside a pattern language. The slides credit Michael Ballantyne as co-developer (racketcon/slides.rkt, line 94).
The papers' URLs and the syntax-spec author list are from the program survey above (search only), not opened here.
8. 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.
10. Notes
- TBD, after the stream.