···7788## Overview
991010-Racket is a language-oriented programming language descended from Scheme. It is NOT simply "another Scheme" — Racket has its own idioms, standard library, macro system, module system, and conventions that differ significantly from R5RS/R6RS/R7RS Scheme and from Common Lisp. Code that looks like "generic Scheme" is usually not idiomatic Racket. Racket developers often call themselves "Racketeers" (in the Scheme tradition of naming things after illicit activities).
1010+Racket is a language-oriented programming language descended from Scheme. It is
1111+NOT simply"another Scheme" — Racket has its own idioms, standard library, macro
1212+system, module system, and conventions that differ significantly from R5RS/R6RS/
1313+R7RS Scheme and from Common Lisp. Code that looks like "generic Scheme" is
1414+usually not idiomatic Racket. Racket developers often call themselves
1515+"Racketeers" (in the Scheme tradition of naming things after illicit activities).
11161212-This skill covers idiomatic Racket style, common pitfalls that AI coding agents make, project structure, testing, macros, and documentation.
1717+This skill covers idiomatic Racket style, common pitfalls that AI coding agents
1818+make, project structure, testing, macros, and documentation.
13191414-**Reference**: The official Racket style guide is at https://docs.racket-lang.org/style/index.html — consult it when uncertain.
2020+**Reference**: The official Racket style guide is at
2121+<https://docs.racket-lang.org/style/index.html> — consult it when uncertain.
15221623---
17241825## Critical: Things AI Agents Get Wrong
19262020-These are the most common mistakes. Internalize these before writing any Racket code.
2727+These are the most common mistakes. Internalize these before writing any Racket
2828+code.
21292230### 1. Do NOT write Scheme — write Racket
2331···3846```
39474048Key differences from Scheme:
4949+4150- Use `#lang racket` (not `#lang scheme` or `#lang r5rs`)
4251- Use square brackets `[]` for cond clauses, let bindings, and for clauses
4343-- Use `for/list`, `for/fold`, `for/hash`, etc. instead of manual recursion over lists
5252+- Use `for/list`, `for/fold`, `for/hash`, etc. instead of manual recursion over
5353+ lists
4454- Use `match` and `match-define` for destructuring, not `car`/`cdr` chains
4555- Use `first`, `rest`, `empty?` over `car`, `cdr`, `null?` (though the latter work)
4656- Use `string-append`, `string-join`, etc. — not `display` with `string-port`
···50605161### 2. Square brackets are conventional, not optional
52625353-Racket uses `[]` by convention in specific positions. This is one of the most visible markers of idiomatic vs non-idiomatic code.
6363+Racket uses `[]` by convention in specific positions. This is one of the most
6464+visible markers of idiomatic vs non-idiomatic code.
54655566```racket
5667;; WRONG — all parens
···6778```
68796980Use `[]` in these positions:
8181+7082- `cond` clauses: `[test expr ...]`
7183- `match` clauses: `[(pattern) expr ...]`
7284- `let`/`let*`/`letrec` bindings: `(let ([x 1] [y 2]) ...)`
···7789- `parameterize` bindings: `(parameterize ([param val]) ...)`
78907991Do NOT use `[]` for:
9292+8093- Function application: use `(f x)` not `[f x]`
8194- Function definitions: use `(define (f x) ...)` not `(define [f x] ...)`
8295- The outermost form of any expression
···99112 (format-output result))
100113```
101114102102-This is the Racket style guide's explicit recommendation. `let*` is appropriate when you need sequential scope explicitly, but a series of `define` forms in a function body is preferred for readability.
115115+This is the Racket style guide's explicit recommendation. `let*` is appropriate
116116+when you need sequential scope explicitly, but a series of `define` forms in a
117117+function body is preferred for readability.
103118104104-**Warning**: `define` in a body context has mutually recursive scope (like `letrec`), not sequential scope (like `let*`). This matters if bindings reference each other. In practice, this rarely causes issues for value bindings but is important for function bindings.
119119+**Warning**: `define` in a body context has mutually recursive scope (like
120120+`letrec`), not sequential scope (like `let*`). This matters if bindings
121121+reference each other. In practice, this rarely causes issues for value bindings
122122+but is important for function bindings.
105123106124### 4. Use `for` loops, not `map`/`filter` with lambda
107125···115133 (* x x))
116134```
117135118118-The `for` family of loops (`for/list`, `for/fold`, `for/hash`, `for/sum`, `for/and`, `for/or`, `for/first`, `for/vector`, etc.) is the idiomatic way to iterate in Racket. They:
136136+The `for` family of loops (`for/list`, `for/fold`, `for/hash`, `for/sum`,
137137+`for/and`, `for/or`, `for/first`, `for/vector`, etc.) is the idiomatic way to
138138+iterate in Racket. They:
139139+119140- Avoid intermediate lambdas
120141- Generalize across sequence types (lists, vectors, hashes, ranges, etc.)
121142- Support `#:when`, `#:unless`, `#:break`, `#:final` clauses
122143- Can iterate over multiple sequences in parallel
123144124124-**Important**: Always use `in-list`, `in-vector`, `in-hash`, `in-range`, etc. in `for` clauses for both clarity and performance. These are macros created with `define-sequence-syntax` and are recognized specially by `for` at compile time, enabling optimized iteration. A bare list variable in a `for` clause works but falls back to the generic (slower) sequence protocol.
145145+**Important**: Always use `in-list`, `in-vector`, `in-hash`, `in-range`, etc. in
146146+`for` clauses for both clarity and performance. These are macros created with
147147+`define-sequence-syntax` and are recognized specially by `for` at compile time,
148148+enabling optimized iteration. A bare list variable in a `for` clause works but
149149+falls back to the generic (slower) sequence protocol.
125150126126-Note that `for` loops (but NOT `for*` loops) iterate multiple sequence clauses in lockstep. This is useful for pairing a sequence with its indices:
151151+Note that `for` loops (but NOT `for*` loops) iterate multiple sequence clauses
152152+in lockstep. This is useful for pairing a sequence with its indices:
127153128154```racket
129155;; Find the index of the first comma in a string starting from pos
···133159 i)
134160```
135161136136-Do NOT use `for/or` with `(and condition value)` as a workaround for this — use `for/first` with a second lockstep clause instead.
162162+Do NOT use `for/or` with `(and condition value)` as a workaround for this —
163163+use `for/first` with a second lockstep clause instead.
137164138165```racket
139166;; WRONG — bare list, slower and less clear
···209236- Mutating procedures end with `!`: `set!`, `vector-set!`, `hash-set!`
210237- Conversion functions use `->`: `string->number`, `list->vector`
211238- Type/struct names are nouns: `point`, `employee`, `syntax-token`
212212-- Do NOT use `_` (underscore) in names — it's reserved for "don't care" patterns in `match` and `syntax-parse`
239239+- Do NOT use `_` (underscore) in names — it's reserved for "don't care" patterns
240240+ in `match` and `syntax-parse`
213241- Avoid plural collection names: prefer `racket/list` not `racket/lists`
214242215243---
···218246219247### Single-collection package (most common)
220248221221-```
249249+```text
222250my-package/
223251├── info.rkt ; Package metadata
224252├── main.rkt ; Primary module (require'd as just "my-package")
···247275248276### Multi-collection package
249277250250-```
278278+```text
251279my-package/
252280├── info.rkt ; (define collection 'multi)
253281├── my-lib/
···266294267295- `raco pkg install` — install a package (from current directory or source)
268296- `raco pkg install --link` — link a local development directory as a package
269269-- `raco setup` — recompile and rebuild *all* installed Racket code. This is the most common workflow during development — no need to track which specific collections changed.
297297+- `raco setup` — recompile and rebuild *all* installed Racket code. This is the
298298+ most common workflow during development — no need to track which specific
299299+ collections changed.
270300- `raco setup <collection>` — recompile and rebuild only a specific collection
271301- `raco test <file-or-directory>` — run tests
272272-- `raco test --drdr <file-or-directory>` — run tests in DrDr mode, which parallelizes test execution and is slightly stricter. This is the default mode used by the Racket package catalog build server, so test with this flag before publishing.
302302+- `raco test --drdr <file-or-directory>` — run tests in DrDr mode, which
303303+ parallelizes test execution and is slightly stricter. This is the default mode
304304+ used by the Racket package catalog build server, so test with this flag before
305305+ publishing.
273306- `raco test -p <package>` — run all tests in a package
274307- `raco docs` — view local documentation
275308- `raco pkg new <name>` — generate a new package skeleton
···295328 (check-equal? (double -3) -6))
296329```
297330298298-The `module+ test` submodule is the idiomatic way to write tests in Racket. Tests live alongside the code they test but only run when explicitly invoked via `raco test`.
331331+The `module+ test` submodule is the idiomatic way to write tests in Racket.
332332+Tests live alongside the code they test but only run when explicitly invoked via
333333+`raco test`.
299334300300-Multiple `module+ test` blocks in the same file are combined into a single test submodule — you can place test blocks near the functions they test. This is a good way to keep files easy to scan. Place the `(module+ test (require rackunit))` part in its own block near the top of the file, alongside the other `require` statements:
335335+Multiple `module+ test` blocks in the same file are combined into a single test
336336+submodule — you can place test blocks near the functions they test. This is a
337337+good way to keep files easy to scan. Place the
338338+`(module+ test (require rackunit))` part in its own block near the top of the
339339+file, alongside the other `require` statements:
301340302341```racket
303342#lang racket/base
···328367 (check-equal? (helper 5) 6))))
329368```
330369331331-Group all test cases for a function under a single `test-case` named after the function. Test cases can be nested in a tree structure, and their names affect the output of testing tools.
370370+Group all test cases for a function under a single `test-case` named after the
371371+function. Test cases can be nested in a tree structure, and their names affect
372372+the output of testing tools.
332373333374### rackunit essentials
334375···350391 (check-equal? (foo 2) 4))
351392```
352393353353-**Avoid `test-suite`.** Test suites predate the submodule system and are rarely useful in modern Racket. They add complexity without much benefit — just use `test-case` for grouping and `module+ test` for structure.
394394+**Avoid `test-suite`.** Test suites predate the submodule system and are rarely
395395+useful in modern Racket. They add complexity without much benefit — just use
396396+`test-case` for grouping and `module+ test` for structure.
354397355398### Separate test files
356399357357-For larger test suites, create a `test/` directory. **Always put tests in `module+ test` submodules**, even in files within a `test/` directory. This eliminates all ambiguity about what is test code vs. non-test code, and ensures tools (like `raco test`, `raco cover`, code stripping for binary packages) treat test code uniformly regardless of where it lives in the file system.
400400+For larger test suites, create a `test/` directory. **Always put tests in
401401+`module+ test` submodules**, even in files within a `test/` directory. This
402402+eliminates all ambiguity about what is test code vs. non-test code, and ensures
403403+tools (like `raco test`, `raco cover`, code stripping for binary packages) treat
404404+test code uniformly regardless of where it lives in the file system.
358405359406---
360407361408## Macros
362409363363-Racket has a powerful, hygienic macro system. There is a hierarchy of macro-definition forms:
410410+Racket has a powerful, hygienic macro system. There is a hierarchy of
411411+macro-definition forms:
364412365413### When to use macros vs functions
366414367367-**Use functions when possible.** The Racket style guide is explicit: do not introduce macros when functions will do. Functions compose better, are usable in higher-order contexts, and are simpler to understand.
415415+**Use functions when possible.** The Racket style guide is explicit: do not
416416+introduce macros when functions will do. Functions compose better, are usable in
417417+higher-order contexts, and are simpler to understand.
368418369419Use macros when you need to:
420420+370421- Control evaluation order (short-circuiting, delayed evaluation)
371422- Introduce new binding forms
372423- Transform syntax (new language constructs)
···375426376427### Macro definition forms
377428378378-**Always use the `syntax-parse` macro system.** The `syntax-rules` and `syntax-case` systems are functionally obsolete in modern Racket. They lack `syntax-parse`'s automatic error reporting, syntax classes, and pattern directives.
429429+**Always use the `syntax-parse` macro system.** The `syntax-rules` and
430430+`syntax-case` systems are functionally obsolete in modern Racket. They lack
431431+`syntax-parse`'s automatic error reporting, syntax classes, and pattern directives.
3794323804331. **`define-syntax-parse-rule`** — simplest, for pattern-only macros (one clause)
381434···388441 (set! b tmp)))
389442```
390443391391-Note: `define-syntax-parse-rule` is the modern name for `define-simple-macro`. Use the former.
444444+Note: `define-syntax-parse-rule` is the modern name for `define-simple-macro`.
445445+Use the former.
392446393393-2. **`define-syntax` + `syntax-parse`** — full power, for anything with multiple clauses, side conditions, or complex logic
447447+1. **`define-syntax` + `syntax-parse`** — full power, for anything with multiple
448448+clauses, side conditions, or complex logic
394449395450```racket
396451(require (for-syntax racket/base syntax/parse))
···401456 #'(cond [test body ...] ...)]))
402457```
403458404404-Do NOT use `define-syntax-rule` for anything nontrivial — it provides no syntax class annotations and produces poor error messages. Prefer `define-syntax-parse-rule` even for simple cases.
459459+Do NOT use `define-syntax-rule` for anything nontrivial — it provides no syntax
460460+class annotations and produces poor error messages. Prefer
461461+`define-syntax-parse-rule` even for simple cases.
405462406463### syntax-parse best practices
407464408465`syntax-parse` is the modern, recommended way to write macros in Racket. It provides:
466466+409467- Syntax classes for reusable pattern components
410468- Automatic error reporting with good messages
411469- Pattern directives (`#:when`, `#:with`, `#:fail-when`, etc.)
···425483```
426484427485Key points:
428428-- Always `(require (for-syntax racket/base syntax/parse))` — these are not automatically available
486486+487487+- Always `(require (for-syntax racket/base syntax/parse))` — these are not
488488+ automatically available
429489- Use `:expr`, `:id`, `:keyword`, `:str`, `:nat`, etc. for built-in syntax classes
430490- Use `...` (ellipsis) for repetition, `...+` for one-or-more
431491- Use `#:literals` to match specific identifiers
···434494435495### Phase levels
436496437437-Racket has a strict phase separation system. Code that runs at compile time (phase 1) must be explicitly required at that phase.
497497+Racket has a strict phase separation system. Code that runs at compile time
498498+(phase 1) must be explicitly required at that phase.
438499439500```racket
440501(require (for-syntax racket/base)) ; phase 1 (compile time)
···443504```
444505445506Common phase-level mistakes:
507507+446508- Forgetting `(require (for-syntax racket/base))` when writing macros
447509- Trying to use a runtime binding at compile time
448510- Forgetting that `begin-for-syntax` runs at phase 1
···490552#lang info ; package metadata (info.rkt files)
491553```
492554493493-Use `#lang racket/base` for library code when you want faster startup and explicit dependencies. Use `#lang racket` for scripts and applications where convenience matters more.
555555+Use `#lang racket/base` for library code when you want faster startup and
556556+explicit dependencies. Use `#lang racket` for scripts and applications where
557557+convenience matters more.
494558495559---
496560···528592 (fprintf port "<employee:~a>" (employee-name emp)))])
529593```
530594531531-`#:transparent` makes structs printable and comparable — use it unless you have a reason not to.
595595+`#:transparent` makes structs printable and comparable — use it unless you have
596596+a reason not to.
532597533598### String operations
534599···637702638703## Third-Party Tools
639704640640-These tools are widely used by Racketeers (the Racket community's name for themselves, in the Scheme tradition of naming things after illicit activities):
705705+These tools are widely used by Racketeers (the Racket community's name for
706706+themselves, in the Scheme tradition of naming things after illicit activities):
641707642642-- **`raco fmt`** — automatic code formatting. Use this to ensure consistent formatting rather than hand-formatting.
643643-- **`resyntax`** — analyzes Racket code and suggests idiomatic improvements. Powered by `syntax-parse`-based refactoring rules. Useful for both learning idiomatic Racket and automated code cleanup.
644644-- **`raco cover`** — generates code coverage reports from tests. Helps identify untested code paths.
708708+- **`raco fmt`** — automatic code formatting. Use this to ensure consistent
709709+ formatting rather than hand-formatting.
710710+- **`resyntax`** — analyzes Racket code and suggests idiomatic improvements.
711711+ Powered by `syntax-parse`-based refactoring rules. Useful for both learning
712712+ idiomatic Racket and automated code cleanup.
713713+- **`raco cover`** — generates code coverage reports from tests. Helps identify
714714+ untested code paths.
645715646716---
647717