AI agent skill files related to programming with Racket

Reformat the skill file

+106 -36
+106 -36
racket.md
··· 7 7 8 8 ## Overview 9 9 10 - 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). 10 + Racket is a language-oriented programming language descended from Scheme. It is 11 + NOT simply"another Scheme" — Racket has its own idioms, standard library, macro 12 + system, module system, and conventions that differ significantly from R5RS/R6RS/ 13 + R7RS Scheme and from Common Lisp. Code that looks like "generic Scheme" is 14 + usually not idiomatic Racket. Racket developers often call themselves 15 + "Racketeers" (in the Scheme tradition of naming things after illicit activities). 11 16 12 - This skill covers idiomatic Racket style, common pitfalls that AI coding agents make, project structure, testing, macros, and documentation. 17 + This skill covers idiomatic Racket style, common pitfalls that AI coding agents 18 + make, project structure, testing, macros, and documentation. 13 19 14 - **Reference**: The official Racket style guide is at https://docs.racket-lang.org/style/index.html — consult it when uncertain. 20 + **Reference**: The official Racket style guide is at 21 + <https://docs.racket-lang.org/style/index.html> — consult it when uncertain. 15 22 16 23 --- 17 24 18 25 ## Critical: Things AI Agents Get Wrong 19 26 20 - These are the most common mistakes. Internalize these before writing any Racket code. 27 + These are the most common mistakes. Internalize these before writing any Racket 28 + code. 21 29 22 30 ### 1. Do NOT write Scheme — write Racket 23 31 ··· 38 46 ``` 39 47 40 48 Key differences from Scheme: 49 + 41 50 - Use `#lang racket` (not `#lang scheme` or `#lang r5rs`) 42 51 - Use square brackets `[]` for cond clauses, let bindings, and for clauses 43 - - Use `for/list`, `for/fold`, `for/hash`, etc. instead of manual recursion over lists 52 + - Use `for/list`, `for/fold`, `for/hash`, etc. instead of manual recursion over 53 + lists 44 54 - Use `match` and `match-define` for destructuring, not `car`/`cdr` chains 45 55 - Use `first`, `rest`, `empty?` over `car`, `cdr`, `null?` (though the latter work) 46 56 - Use `string-append`, `string-join`, etc. — not `display` with `string-port` ··· 50 60 51 61 ### 2. Square brackets are conventional, not optional 52 62 53 - Racket uses `[]` by convention in specific positions. This is one of the most visible markers of idiomatic vs non-idiomatic code. 63 + Racket uses `[]` by convention in specific positions. This is one of the most 64 + visible markers of idiomatic vs non-idiomatic code. 54 65 55 66 ```racket 56 67 ;; WRONG — all parens ··· 67 78 ``` 68 79 69 80 Use `[]` in these positions: 81 + 70 82 - `cond` clauses: `[test expr ...]` 71 83 - `match` clauses: `[(pattern) expr ...]` 72 84 - `let`/`let*`/`letrec` bindings: `(let ([x 1] [y 2]) ...)` ··· 77 89 - `parameterize` bindings: `(parameterize ([param val]) ...)` 78 90 79 91 Do NOT use `[]` for: 92 + 80 93 - Function application: use `(f x)` not `[f x]` 81 94 - Function definitions: use `(define (f x) ...)` not `(define [f x] ...)` 82 95 - The outermost form of any expression ··· 99 112 (format-output result)) 100 113 ``` 101 114 102 - 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. 115 + This is the Racket style guide's explicit recommendation. `let*` is appropriate 116 + when you need sequential scope explicitly, but a series of `define` forms in a 117 + function body is preferred for readability. 103 118 104 - **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. 119 + **Warning**: `define` in a body context has mutually recursive scope (like 120 + `letrec`), not sequential scope (like `let*`). This matters if bindings 121 + reference each other. In practice, this rarely causes issues for value bindings 122 + but is important for function bindings. 105 123 106 124 ### 4. Use `for` loops, not `map`/`filter` with lambda 107 125 ··· 115 133 (* x x)) 116 134 ``` 117 135 118 - 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: 136 + The `for` family of loops (`for/list`, `for/fold`, `for/hash`, `for/sum`, 137 + `for/and`, `for/or`, `for/first`, `for/vector`, etc.) is the idiomatic way to 138 + iterate in Racket. They: 139 + 119 140 - Avoid intermediate lambdas 120 141 - Generalize across sequence types (lists, vectors, hashes, ranges, etc.) 121 142 - Support `#:when`, `#:unless`, `#:break`, `#:final` clauses 122 143 - Can iterate over multiple sequences in parallel 123 144 124 - **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. 145 + **Important**: Always use `in-list`, `in-vector`, `in-hash`, `in-range`, etc. in 146 + `for` clauses for both clarity and performance. These are macros created with 147 + `define-sequence-syntax` and are recognized specially by `for` at compile time, 148 + enabling optimized iteration. A bare list variable in a `for` clause works but 149 + falls back to the generic (slower) sequence protocol. 125 150 126 - Note that `for` loops (but NOT `for*` loops) iterate multiple sequence clauses in lockstep. This is useful for pairing a sequence with its indices: 151 + Note that `for` loops (but NOT `for*` loops) iterate multiple sequence clauses 152 + in lockstep. This is useful for pairing a sequence with its indices: 127 153 128 154 ```racket 129 155 ;; Find the index of the first comma in a string starting from pos ··· 133 159 i) 134 160 ``` 135 161 136 - Do NOT use `for/or` with `(and condition value)` as a workaround for this — use `for/first` with a second lockstep clause instead. 162 + Do NOT use `for/or` with `(and condition value)` as a workaround for this — 163 + use `for/first` with a second lockstep clause instead. 137 164 138 165 ```racket 139 166 ;; WRONG — bare list, slower and less clear ··· 209 236 - Mutating procedures end with `!`: `set!`, `vector-set!`, `hash-set!` 210 237 - Conversion functions use `->`: `string->number`, `list->vector` 211 238 - Type/struct names are nouns: `point`, `employee`, `syntax-token` 212 - - Do NOT use `_` (underscore) in names — it's reserved for "don't care" patterns in `match` and `syntax-parse` 239 + - Do NOT use `_` (underscore) in names — it's reserved for "don't care" patterns 240 + in `match` and `syntax-parse` 213 241 - Avoid plural collection names: prefer `racket/list` not `racket/lists` 214 242 215 243 --- ··· 218 246 219 247 ### Single-collection package (most common) 220 248 221 - ``` 249 + ```text 222 250 my-package/ 223 251 ├── info.rkt ; Package metadata 224 252 ├── main.rkt ; Primary module (require'd as just "my-package") ··· 247 275 248 276 ### Multi-collection package 249 277 250 - ``` 278 + ```text 251 279 my-package/ 252 280 ├── info.rkt ; (define collection 'multi) 253 281 ├── my-lib/ ··· 266 294 267 295 - `raco pkg install` — install a package (from current directory or source) 268 296 - `raco pkg install --link` — link a local development directory as a package 269 - - `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. 297 + - `raco setup` — recompile and rebuild *all* installed Racket code. This is the 298 + most common workflow during development — no need to track which specific 299 + collections changed. 270 300 - `raco setup <collection>` — recompile and rebuild only a specific collection 271 301 - `raco test <file-or-directory>` — run tests 272 - - `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. 302 + - `raco test --drdr <file-or-directory>` — run tests in DrDr mode, which 303 + parallelizes test execution and is slightly stricter. This is the default mode 304 + used by the Racket package catalog build server, so test with this flag before 305 + publishing. 273 306 - `raco test -p <package>` — run all tests in a package 274 307 - `raco docs` — view local documentation 275 308 - `raco pkg new <name>` — generate a new package skeleton ··· 295 328 (check-equal? (double -3) -6)) 296 329 ``` 297 330 298 - 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`. 331 + The `module+ test` submodule is the idiomatic way to write tests in Racket. 332 + Tests live alongside the code they test but only run when explicitly invoked via 333 + `raco test`. 299 334 300 - 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: 335 + Multiple `module+ test` blocks in the same file are combined into a single test 336 + submodule — you can place test blocks near the functions they test. This is a 337 + good way to keep files easy to scan. Place the 338 + `(module+ test (require rackunit))` part in its own block near the top of the 339 + file, alongside the other `require` statements: 301 340 302 341 ```racket 303 342 #lang racket/base ··· 328 367 (check-equal? (helper 5) 6)))) 329 368 ``` 330 369 331 - 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. 370 + Group all test cases for a function under a single `test-case` named after the 371 + function. Test cases can be nested in a tree structure, and their names affect 372 + the output of testing tools. 332 373 333 374 ### rackunit essentials 334 375 ··· 350 391 (check-equal? (foo 2) 4)) 351 392 ``` 352 393 353 - **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. 394 + **Avoid `test-suite`.** Test suites predate the submodule system and are rarely 395 + useful in modern Racket. They add complexity without much benefit — just use 396 + `test-case` for grouping and `module+ test` for structure. 354 397 355 398 ### Separate test files 356 399 357 - 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. 400 + For larger test suites, create a `test/` directory. **Always put tests in 401 + `module+ test` submodules**, even in files within a `test/` directory. This 402 + eliminates all ambiguity about what is test code vs. non-test code, and ensures 403 + tools (like `raco test`, `raco cover`, code stripping for binary packages) treat 404 + test code uniformly regardless of where it lives in the file system. 358 405 359 406 --- 360 407 361 408 ## Macros 362 409 363 - Racket has a powerful, hygienic macro system. There is a hierarchy of macro-definition forms: 410 + Racket has a powerful, hygienic macro system. There is a hierarchy of 411 + macro-definition forms: 364 412 365 413 ### When to use macros vs functions 366 414 367 - **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. 415 + **Use functions when possible.** The Racket style guide is explicit: do not 416 + introduce macros when functions will do. Functions compose better, are usable in 417 + higher-order contexts, and are simpler to understand. 368 418 369 419 Use macros when you need to: 420 + 370 421 - Control evaluation order (short-circuiting, delayed evaluation) 371 422 - Introduce new binding forms 372 423 - Transform syntax (new language constructs) ··· 375 426 376 427 ### Macro definition forms 377 428 378 - **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. 429 + **Always use the `syntax-parse` macro system.** The `syntax-rules` and 430 + `syntax-case` systems are functionally obsolete in modern Racket. They lack 431 + `syntax-parse`'s automatic error reporting, syntax classes, and pattern directives. 379 432 380 433 1. **`define-syntax-parse-rule`** — simplest, for pattern-only macros (one clause) 381 434 ··· 388 441 (set! b tmp))) 389 442 ``` 390 443 391 - Note: `define-syntax-parse-rule` is the modern name for `define-simple-macro`. Use the former. 444 + Note: `define-syntax-parse-rule` is the modern name for `define-simple-macro`. 445 + Use the former. 392 446 393 - 2. **`define-syntax` + `syntax-parse`** — full power, for anything with multiple clauses, side conditions, or complex logic 447 + 1. **`define-syntax` + `syntax-parse`** — full power, for anything with multiple 448 + clauses, side conditions, or complex logic 394 449 395 450 ```racket 396 451 (require (for-syntax racket/base syntax/parse)) ··· 401 456 #'(cond [test body ...] ...)])) 402 457 ``` 403 458 404 - 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. 459 + Do NOT use `define-syntax-rule` for anything nontrivial — it provides no syntax 460 + class annotations and produces poor error messages. Prefer 461 + `define-syntax-parse-rule` even for simple cases. 405 462 406 463 ### syntax-parse best practices 407 464 408 465 `syntax-parse` is the modern, recommended way to write macros in Racket. It provides: 466 + 409 467 - Syntax classes for reusable pattern components 410 468 - Automatic error reporting with good messages 411 469 - Pattern directives (`#:when`, `#:with`, `#:fail-when`, etc.) ··· 425 483 ``` 426 484 427 485 Key points: 428 - - Always `(require (for-syntax racket/base syntax/parse))` — these are not automatically available 486 + 487 + - Always `(require (for-syntax racket/base syntax/parse))` — these are not 488 + automatically available 429 489 - Use `:expr`, `:id`, `:keyword`, `:str`, `:nat`, etc. for built-in syntax classes 430 490 - Use `...` (ellipsis) for repetition, `...+` for one-or-more 431 491 - Use `#:literals` to match specific identifiers ··· 434 494 435 495 ### Phase levels 436 496 437 - Racket has a strict phase separation system. Code that runs at compile time (phase 1) must be explicitly required at that phase. 497 + Racket has a strict phase separation system. Code that runs at compile time 498 + (phase 1) must be explicitly required at that phase. 438 499 439 500 ```racket 440 501 (require (for-syntax racket/base)) ; phase 1 (compile time) ··· 443 504 ``` 444 505 445 506 Common phase-level mistakes: 507 + 446 508 - Forgetting `(require (for-syntax racket/base))` when writing macros 447 509 - Trying to use a runtime binding at compile time 448 510 - Forgetting that `begin-for-syntax` runs at phase 1 ··· 490 552 #lang info ; package metadata (info.rkt files) 491 553 ``` 492 554 493 - 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. 555 + Use `#lang racket/base` for library code when you want faster startup and 556 + explicit dependencies. Use `#lang racket` for scripts and applications where 557 + convenience matters more. 494 558 495 559 --- 496 560 ··· 528 592 (fprintf port "<employee:~a>" (employee-name emp)))]) 529 593 ``` 530 594 531 - `#:transparent` makes structs printable and comparable — use it unless you have a reason not to. 595 + `#:transparent` makes structs printable and comparable — use it unless you have 596 + a reason not to. 532 597 533 598 ### String operations 534 599 ··· 637 702 638 703 ## Third-Party Tools 639 704 640 - These tools are widely used by Racketeers (the Racket community's name for themselves, in the Scheme tradition of naming things after illicit activities): 705 + These tools are widely used by Racketeers (the Racket community's name for 706 + themselves, in the Scheme tradition of naming things after illicit activities): 641 707 642 - - **`raco fmt`** — automatic code formatting. Use this to ensure consistent formatting rather than hand-formatting. 643 - - **`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. 644 - - **`raco cover`** — generates code coverage reports from tests. Helps identify untested code paths. 708 + - **`raco fmt`** — automatic code formatting. Use this to ensure consistent 709 + formatting rather than hand-formatting. 710 + - **`resyntax`** — analyzes Racket code and suggests idiomatic improvements. 711 + Powered by `syntax-parse`-based refactoring rules. Useful for both learning 712 + idiomatic Racket and automated code cleanup. 713 + - **`raco cover`** — generates code coverage reports from tests. Helps identify 714 + untested code paths. 645 715 646 716 --- 647 717