Best for
- Use when working with Racket code.
Pyroxin/opinionated-claude-skills/opinionated-lisp-development/skills/racket-programmer/SKILL.md
Racket-specific tooling, libraries, idioms, and language-oriented programming philosophy. Use when working with Racket code. Emphasizes LOP, contracts, macros, and design methodology.
Decision brief
Expert-level Racket programming skill focused on judgment frameworks, language-oriented programming philosophy, and production practices.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/Pyroxin/opinionated-claude-skills --skill "opinionated-lisp-development/skills/racket-programmer"Inspect the Agent Skill "racket-programmer" from https://github.com/Pyroxin/opinionated-claude-skills/blob/10c332aaec223fb10f63174029c4803f77eac269/opinionated-lisp-development/skills/racket-programmer/SKILL.md at commit 10c332aaec223fb10f63174029c4803f77eac269. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Installation: raco pkg install review
Always target the latest stable Racket version unless explicitly working on a codebase with version constraints.
Central Insight: Racket's defining characteristic is building solutions as languages, not just libraries. Every problem is approached by asking "what's the right notation?" before "what's the implementation?"
"A programmable programming language." Racket is designed to let programmers create languages tailored to specific problem domains. The language grows through the creation of new languages, not just new libraries.
Review the “Decision Framework: lang vs Library vs Macro” section in the pinned source before continuing.
Permission review
The documentation asks the agent to read local files, directories, or repositories.
(parameterize ([current-output-port (open-output-file "log.txt")])Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 95/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 8 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Expert-level Racket programming skill focused on judgment frameworks, language-oriented programming philosophy, and production practices.
Related skills:
software-engineer - Core programming philosophy and SICP principles that underpin Racket's designfunctional-programmer - FP patterns and thinking (Racket is fundamentally functional)test-driven-development - General testing philosophy; this skill covers RackUnit specificsAlways target the latest stable Racket version unless explicitly working on a codebase with version constraints.
Racket CS (Chez Scheme-based) is the default implementation since 8.0. Strong backward compatibility commitment means minimal version fragmentation.
For owned codebases: Aggressive upgrade philosophy. Use latest features and libraries.
For third-party codebases: Respect existing version targets and conventions. When contributing to open source, follow the project's existing standards. Don't introduce modern features to projects targeting older versions. Propose improvements through proper channels (issues, governance).
<language_oriented_programming>
Central Insight: Racket's defining characteristic is building solutions as languages, not just libraries. Every problem is approached by asking "what's the right notation?" before "what's the implementation?"
This is not a feature of Racket—it IS Racket's design philosophy. Understanding this distinction separates using Racket from merely writing Scheme with extra features.
"A programmable programming language." Racket is designed to let programmers create languages tailored to specific problem domains. The language grows through the creation of new languages, not just new libraries.
Key principle: "If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization." —Gerald Weinberg
The right notation eliminates entire classes of errors at compile time. Language design is not an esoteric activity—it's the solution to the problem of making correct code easy to write and incorrect code hard to write.
Does solution need non-S-expression syntax?
→ Reader extension needed → #lang
Does solution benefit from compile-time validation of entire program?
→ Custom #%module-begin → #lang
Just adding new operations/abstractions?
→ Macros + provide → library
Need IDE integration (syntax coloring, specialized checks)?
→ #lang with language info
Notation precision outweighs learning curve?
→ #lang
Essential Reading:
Trade-offs:
Pattern: Build languages on languages, creating towers where each layer provides abstractions for the next. Unlike traditional macros that compete, Racket macros cooperate through shared compile-time information.
Key Paper: "Macros that Work Together" (Flatt et al., 2012)
Racket achieves this through:
Example: Racket's class system is implemented as macros over struct, which is itself a macro. Each layer maintains proper scoping and composition.
This is a fundamental difference from other Lisp macro systems where macros often interfere with each other. </language_oriented_programming>
<contracts_and_blame>
Core Pattern: Modules are units of abstraction AND units of blame for contracts. Design module boundaries intentionally with this in mind.
Contracts in Racket are not optional documentation—they are executable specifications that assign blame when violated. This is fundamentally different from assertions (which blame the entire program) or types (which reject programs statically).
(provide
(contract-out
[my-function (→ number? (>/c 0) boolean?)]
[my-struct (struct/c point [real? real?])]
[complex-fn (→i ([x number?]
[y (x) (>/c x)]) ; dependent contract
[result number?])]))
Public API boundary?
→ REQUIRED: contract-out with precise contracts
Internal module function?
→ Optional: Consider for complex invariants
Performance-critical inner loop?
→ Profile first (contracts typically cheap, but measure)
Complex invariant (e.g., balanced tree)?
→ Use dependent contracts (→i)
Simple type-like guarantee?
→ Flat contracts (number?, string?)
Chaperone vs Impersonator Contracts:
Key Resources:
<macro_system>
| Need | Tool | When to Use |
|---|---|---|
| Simple substitution | define-syntax-rule | One-off macros, prototyping |
| Multiple patterns | syntax-rules | Standard pattern matching, no validation |
| Validation + errors | syntax/parse | Production macros (recommended) |
| Complex compile logic | define-syntax + procedure | Programmatic code generation |
| Syntax templates | with-syntax, quasisyntax | Building syntax from data |
(define-syntax (my-let stx)
(syntax-parse stx
[(_ ([var:id rhs:expr] ...) body:expr ...+)
#:fail-when (check-duplicate-identifier (syntax->list #'(var ...)))
"duplicate variable name"
#'(let ([var rhs] ...) body ...)]))
Why syntax/parse for production:
#:fail-whenEssential Resources:
Hygiene: Racket macros are hygienic by default. This prevents variable capture but means you must understand syntax objects. Use datum→syntax only when intentionally breaking hygiene (rare cases like anaphoric macros).
Decision Tree:
Modify single character interpretation?
→ Readtable (make-readtable)
Embedded DSL with different syntax?
→ Readtable + #reader
Complete language with custom notation?
→ #lang + reader module
Compatible with S-expressions?
→ DON'T use reader - use macros instead!
When to Extend Reader:
When NOT to:
Trade-offs:
<structs_vs_classes>
Decision Framework:
Representing data with operations?
→ Struct (90% of use cases)
Need inheritance-based polymorphism with method overriding?
→ Class
Building GUI application?
→ Class (Racket GUI framework uses classes)
Need polymorphism but not inheritance?
→ Struct with generic interfaces (#:methods gen:custom)
Porting OO codebase?
→ Class (but consider refactoring to structs)
#:methods with generics(define-generics printable
(print-it printable port))
(struct point (x y)
#:methods gen:printable
[(define (print-it p port)
(fprintf port "(~a,~a)" (point-x p) (point-y p)))])
Staff Guidance: Default to structs. Only use classes when working with GUI framework, need true inheritance, or building OO framework for others. When unsure, start with structs + generics. </structs_vs_classes>
<typed_racket>
Performance-critical numeric code?
→ YES (25-50× speedups possible)
Large-scale refactoring/maintenance?
→ YES (types document invariants)
Complex data structure invariants?
→ YES (occurrence typing + refinements)
Heavy typed/untyped interaction?
→ CAUTION (contract overhead can be severe)
Exploratory/prototype code?
→ NO (friction not worth it)
Macro-heavy DSLs?
→ NO (limitations on macro usage)
#lang typed/racket ; Deep types (default, full checking)
#lang typed/racket/shallow ; Shallow types (lower overhead)
#lang typed/racket/optional ; Optional types (no runtime cost)
Racket's type system has occurrence typing—type refinement based on predicates:
(: flexible-length (→ (U String (Listof Any)) Integer))
(define (flexible-length x)
(if (string? x)
(string-length x) ; x refined to String here
(length x))) ; x refined to (Listof Any) here
This is a distinctive feature compared to most gradual type systems.
Float not Real for numeric optimizationEssential Resources:
<functional_idioms>
What Makes Racket FP Unique (not generic FP advice that you already know):
Not just type checking; express behavioral constraints. Contracts are values that can be computed and composed.
Compile-time computation is functional programming. Phase separation keeps concerns clean.
Better than global variables for cross-cutting concerns:
;; Standard pattern for context
(parameterize ([current-output-port (open-output-file "log.txt")])
(displayln "logged"))
Example: current-output-port, current-directory
;; Prefer for/* comprehensions over explicit recursion
(for/list ([x (in-range 10)]
#:when (even? x))
(* x x))
(define (eval expr)
(match expr
[(? number? n) n]
[`(+ ,a ,b) (+ (eval a) (eval b))]
[`(* ,a ,b) (* (eval a) (eval b))]))
<pattern_matching>
Use match when:
Don't use match for:
cond or if)let)Key Patterns:
;; Struct patterns
(match point
[(point x y) ...])
;; Quasiquote for S-expressions
(match expr
[`(if ,cond ,then ,else) ...])
;; Guards
(match x
[(? number? n) ...]
[(list a b) #:when (> a b) ...])
;; Or patterns
(match expr
[(or (list 'add x y) (list '+ x y)) ...])
</pattern_matching>
<tooling_and_standards>
Decision Rule:
Production library code → #lang racket/base (REQUIRED)
Scripts/demos/exploration → #lang racket (acceptable)
Why racket/base for libraries:
Quote from Beautiful Racket: "As a rule of thumb, it's better practice to start with racket/base and use require to import what you need."
Installation: raco pkg install fmt
Usage:
raco fmt -i file.rkt # Format in-place
raco fmt --width 102 file.rkt # Custom width (style guide default)
raco fmt --check file.rkt # Check without modifying (CI usage)
CI Integration: Add raco fmt --check to fail builds on formatting violations
What it Enforces:
--width 102 for style guide compliance)[...] in specific contexts: let, for, cond, match, caseInstallation: raco pkg install review
Usage:
raco review file.rkt
raco review . # Review entire directory
What It Detects:
Ignoring Warnings:
#|review: ignore|# ; Ignore entire file
(define x 5) ;; review: ignore ; Ignore line
For general testing philosophy, see the test-driven-development skill. Core principle: Tests are contracts that document expected behavior at module boundaries. This skill covers RackUnit-specific patterns.
Basic Usage:
(require rackunit)
;; Simple checks
(check-equal? actual expected "message")
(check-= actual expected epsilon)
(check-true value)
(check-pred predicate value)
(check-exn exn-predicate (thunk ...))
Test Suites:
(define my-tests
(test-suite
"Suite name"
(test-case "Test 1"
(check-equal? (foo 5) 10))
(test-case "Test 2"
(check-true (bar "test")))))
(run-tests my-tests)
module+ test Pattern:
#lang racket/base
(define (my-function x)
(+ x 1))
(provide my-function)
(module+ test
(require rackunit)
(check-equal? (my-function 5) 6)
(check-equal? (my-function 0) 1))
Running Tests:
raco test file.rkt # Test single file
raco test -p package-name # Test entire package
Basic Document Structure:
#lang scribble/manual
@(require (for-label racket my-lib))
@title{My Library}
@defmodule[my-lib]
@defproc[(my-function [arg1 string?] [arg2 integer?])
boolean?]{
Description of what the function does.
@examples[
#:eval my-eval
(my-function "hello" 42)
]
}
MANDATORY: All exported bindings in production code must have Scribble documentation.
Building:
scribble --html manual.scrbl
raco setup --doc-index --pkgs my-package
Primary Resource: https://docs.racket-lang.org/style/index.html
Critical Rules:
| Character | Meaning | Example |
|---|---|---|
? | Predicates | boolean?, even? |
! | Mutators | set!, vector-set! |
% | Classes | button%, frame% |
<> | Interfaces | dc<%>, window<%> |
^ | Unit signatures | game-context^ |
@ | Units | testing-context@ |
#% | Kernel forms | #%app, #%module-begin |
/ | "with" preposition | call/cc, for/list |
Standard Pattern: type-operation (e.g., string-append, hash-ref, list->vector)
#lang racket/base ; Language line (first line)
;; Exports (provide forms first, ideally)
(provide (contract-out
[function (→ Type Type)]
[struct-name ...]))
;; Imports (require forms grouped)
(require racket/list
racket/match
(for-syntax racket/base))
;; Implementation
(define ...)
(struct ...)
For non-trivial libraries:
my-library/
my-library-lib/ # Runtime code only
info.rkt
main.rkt
core/
module1.rkt
my-library-test/ # Tests only
info.rkt
tests/
test-module1.rkt
my-library-doc/ # Documentation only
info.rkt
scribblings/
my-library.scrbl
my-library/ # Composite meta-package
info.rkt # Aggregates all components
Why This Pattern:
-lib, not test/doc depsAuthoritative Resource: https://countvajhula.com/2022/02/22/how-to-organize-your-racket-library/
For small libraries:
my-simple-lib/
main.rkt
helper.rkt
tests/
main-test.rkt
scribblings/
my-simple-lib.scrbl
info.rkt
Core Commands:
raco pkg install package-name # From catalog
raco pkg install github://user/repo/branch
raco pkg update package-name
raco pkg update --all
raco pkg remove package-name --auto # Remove + unused deps
raco pkg show --all # List all packages
Declaring Dependencies in info.rkt (MANDATORY):
#lang info
(define deps
'("base" # Always required
"rackunit-lib"
"web-server-lib"
["other-package" "2.0"])) # Version constraint
(define build-deps
'("scribble-lib" # For docs
"racket-doc")) # For doc cross-refs
Key Fields:
deps: Runtime dependencies (REQUIRED)build-deps: Build-time only (tests, docs)implies: Re-exports for meta-packages
</tooling_and_standards><ci_cd_integration>
GitHub Actions Standard Setup:
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
racket-version: ['8.16', '8.17', 'stable']
variant: ['CS']
steps:
- uses: actions/checkout@v3
- name: Setup Racket
uses: Bogdanp/[email protected]
with:
architecture: 'x64'
distribution: 'full'
variant: ${{ matrix.variant }}
version: ${{ matrix.racket-version }}
- name: Install Dependencies
run: raco pkg install --auto --batch
- name: Check Dependencies
run: raco setup --check-pkg-deps --pkgs my-package
- name: Run Tests
run: raco test --package my-package
- name: Build Documentation
run: raco setup --doc-index --pkgs my-package
- name: Lint Code
run: |
raco pkg install --auto review
raco review .
- name: Check Formatting
run: |
raco pkg install --auto fmt
raco fmt --check .
What MUST Fail Builds:
raco test failures (REQUIRED)raco setup --check-pkg-deps failures (REQUIRED)raco review violations (RECOMMENDED)raco fmt --check failures (if using formatter)<common_mistakes>
<from_scheme>
Key Differences:
Immutable Pairs by Default: Racket pairs are immutable. No set-car!/set-cdr!. Use mcons/mcar/mcdr for mutable pairs.
Module System: Racket's modules are NOT R6RS-compatible. Must use #lang racket not R6RS module syntax.
Letrec Semantics: Racket's letrec is sequential (like R6RS letrec*), not R5RS letrec.
Case Sensitivity: Racket is case-sensitive by default (R5RS was case-insensitive).
Pattern Matching: Not in standard Scheme; heavily used in Racket. Learn match.
Resources:
<from_common_lisp>
Major Differences:
Lisp-1 vs Lisp-2: Racket has unified namespace. No funcall, no #' notation. Functions are first-class values.
;; Racket (Lisp-1):
(map f list)
;; NOT: (mapcar #'f list)
Hygienic Macros: Racket uses syntax-case/syntax-rules (hygienic), not defmacro (unhygienic). Variable capture prevented automatically.
nil vs #f: CL conflates false and empty list. Racket separates #f and '().
No CLOS: Racket's class system is fundamentally different from CLOS. Prefer structs in Racket.
Package vs Module: Different semantics. Racket modules are lexically scoped, not global like CL packages. </from_common_lisp>
<from_clojure>
The #1 Issue: Collections
Clojure Advantages Racket Lacks:
assoc, conj, get){:a 1} for maps, [1 2 3] for vectorsRacket Weaknesses:
Anti-Pattern: Trying to use Racket hash tables like Clojure maps
;; Awkward in Racket:
(hash-set (hash-set h 'a 1) 'b 2) ; nested updates
;; vs Clojure:
(assoc h :a 1 :b 2)
Other Differences:
→ and →→ (can be added via library)Essential Reading: Mark Engelberg's "Racket vs. Clojure": http://programming-puzzler.blogspot.com/2010/08/racket-vs-clojure.html </from_clojure>
<from_haskell>
Type System Differences:
Dynamic by Default: Racket is dynamically typed. Typed Racket is optional, gradual typing (not inference-based).
No Purity Enforcement: Racket allows mutation. Functions ending in ! mutate by convention. No IO monad.
No Automatic Currying: Must use curry explicitly or lambda.
Strict Evaluation: Lists are strict, not lazy. Must explicitly use streams/generators for laziness.
Pattern Matching Not in Function Definitions: Use match or cond, not Haskell-style definition patterns.
No Type Classes: Use generic interfaces or struct methods instead.
Anti-Patterns:
<from_python>
The Functional Paradigm Shift:
Anti-Pattern #1: Global Mutable State
;; BAD (imperative):
(define stack '())
(define (push-stack! item)
(set! stack (cons item stack)))
;; GOOD (functional):
(define (push-stack item stack)
(cons item stack))
Anti-Pattern #2: Loops Instead of Recursion
# Python approach
def sum_list(lst):
total = 0
for item in lst:
total += item
return total
;; Racket approaches:
;; Recursion
(define (sum-list lst)
(if (null? lst) 0
(+ (car lst) (sum-list (cdr lst)))))
;; Higher-order functions
(define (sum-list lst)
(foldl + 0 lst))
Other Mistakes:
for/* comprehensionsset! frequently → prefer define with constantsmap, filter, fold
</from_python><general_anti_patterns>
Code Organization:
match for structured dataPerformance:
(append result (list item)) in loop → O(n²), use cons + reverse(= (length lst) 0) → use (null? lst) insteadTesting:
<units_and_signatures>
Historical Context: Units were inspired by ML functors. Modern Racket uses them rarely (niche feature).
Use units ONLY when:
Don't use for:
Modern Alternatives:
Use For: Pure computation that can run in parallel
Common Mistakes:
Blocking Operations Kill Parallelism
Not Using futures-visualizer
racket -l future-visualizer
Shows which operations blocked parallelism.
Expecting Parallel GC
Use For: True OS-level parallelism, separate memory spaces
Common Mistakes:
place-channel for message passingUse For: Concurrency (I/O, event handling), not CPU parallelism
Key Points:
<performance_profiling>
Statistical Profiler:
(require profile)
(profile
(my-expensive-function))
Command-Line:
PLTSTDERR="debug@profile" racket program.rkt
Feature-Specific Profiler:
raco feature-profile file.rkt # Costs by feature (match, contracts, etc.)
raco contract-profile file.rkt # Contract overhead breakdown
Optimization Coach (DrRacket):
<production_checklist>
MUST HAVE:
#lang racket/base (not #lang racket) for librariescontract-out)rackunit, module+ test)info.rktraco fmtraco review without violationsraco test (MUST pass)raco setup --check-pkg-deps (MUST pass)raco review (SHOULD pass)raco fmt --check (SHOULD pass)SHOULD HAVE:
<decision_frameworks_summary>
Problem needs custom notation?
→ Try macros first
→ If macros insufficient → #lang
→ If compatible with S-expressions → definitely just macros
Performance-critical numeric code OR large codebase?
→ Typed Racket (Deep types)
Heavy typed/untyped boundaries?
→ Shallow types or profile-guided migration
Exploratory code?
→ Stay untyped
Representing data?
→ Struct (90% of cases)
Need inheritance + method overriding?
→ Class
Need polymorphism without inheritance?
→ Struct + generic interfaces
Public API?
→ REQUIRED: contract-out
Internal function?
→ Optional unless complex invariants
Performance critical?
→ Profile first (usually not a problem)
Small project?
→ module+ test in same file
Library?
→ Separate test package (lib/test/doc pattern)
Always run in CI?
→ YES: raco test --package name
</decision_frameworks_summary>
<core_principles> Core Principles:
racket for scriptsWhen in doubt, study how Racket's own core libraries are organized and follow those patterns. </core_principles>
Frequently asked questions
Expert-level Racket programming skill focused on judgment frameworks, language-oriented programming philosophy, and production practices.
The source record exposes this install command: npx skills add https://github.com/Pyroxin/opinionated-claude-skills --skill "opinionated-lisp-development/skills/racket-programmer". Inspect the command and pinned source before running it.
Static rules flagged read-files in the source; the page lists the matching lines and excerpts.
Alternatives
coreyhaines31/marketingskills
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
narrative-io/narrative-skills-marketplace
Translate a fuzzy analytical question into a rigorous investigation plan. Interrogates the ask, grounds the plan in the available data dictionary, applies analytical best practices, and produces a structured brief of query specifications for a downstream query-writing skill. Plans, does not write SQL. Use when: "why did X drop", "is there a relationship between A and B", "who are our highest-value customers", "what's driving the change in Y", "investigate this trend", "design an analysis for", "
vasilyu1983/AI-Agents-public
Guides iOS testing with XCTest, XCUITest, Swift Testing, simctl, and xcresult. Use when choosing destinations, controlling flakes, or parsing test artifacts for native apps.
vasilyu1983/AI-Agents-public
Consumer-neuroscience primitives for attention, arousal, bonding, narrative, memory, and reward. Use when shaping ethical UX, neuro study design, or DMCC/AI Act gates.