Racket Cheat Sheet
Lang Declaration
Every Racket file must start with a #lang directive specifying the language variant:
1#lang racket/base ; Minimal core
2#lang racket ; Standard library
3#lang at-exp racket ; @ notation for string interpolation
Exports & Contracts
Contracts with exports (preferred pattern for library code):
1(provide (contract-out
2 [function-name (-> string? number? boolean?)]
3 [process-data (->* (string?) (number?) list?)])) ; optional params
Simple exports (for internal code):
1(provide function-name
2 another-function)
Submodules
Test submodule - code only runs during raco test:
1(module+ test
2 (require rackunit)
3 (test-case "description"
4 (check-equal? (add 2 3) 5)))
Main submodule - entry point when file runs as script:
1(module+ main
2 (define args (current-command-line-arguments))
3 (start-app args))
Defining Racket Functions with Contracts
Basic Contracts
1; Simple function: string -> number -> boolean
2(define/contract (validate-input text count)
3 (-> string? number? boolean?)
4 (> (string-length text) count))
Optional Parameters
1; Required param, optional param, returns string
2(define/contract (format-message msg [prefix "Info"])
3 (->* (string?) (string?) string?)
4 (string-append prefix ": " msg))
Multiple Value Returns
1; Function returning two values
2(define (http-request url)
3 (values response-body status-code))
4
5; Consuming multiple values
6(define-values (body status) (http-request "http://api.example.com"))
Racket String Manipulation and Interpolation
String Interpolation with @-expressions
1#lang at-exp racket ; Required in lang declaration
2
3(define api-key "abc123")
4(define url @string-append{
5 https://api.example.com/v1/data?key=@|api-key|&format=json
6})
Common String Functions
1(string-append "hello" " " "world") ; Concatenation
2(string-join '("a" "b" "c") ", ") ; Join list
3(string-split "a,b,c" ",") ; Split to list
4(string-trim " text ") ; Trim whitespace
5(string-downcase "HELLO") ; Lowercase
6(string-replace "hello" "l" "L") ; Replace
7(format "~a is ~a" name value) ; Format string
String/Bytes Conversion
1; Critical for HTTP and crypto operations
2(string->bytes/utf-8 "text") ; string -> bytes
3(bytes->string/utf-8 #"bytes") ; bytes -> string
Core Data Structures: Lists & Hashes
Association Lists (alists)
Preferred for headers and key-value pairs:
1; Creating
2(define headers
3 '(("Content-Type" . "application/json")
4 ("Authorization" . "Bearer token")))
5
6; Accessing with case-insensitive comparison
7(define (get-header name headers)
8 (match (assoc name headers string-ci=?)
9 [(cons _ value) value]
10 [_ #f]))
Hashes
1; Immutable hash from alist
2(define headers-hash
3 (make-immutable-hash
4 (map (λ (pr) (cons (string->symbol (car pr)) (cdr pr)))
5 headers-alist)))
6
7; Hash operations
8(hash 'key1 "value1" 'key2 "value2") ; Create
9(hash-ref h 'key) ; Get
10(hash-set h 'key "value") ; Set (immutable)
Pattern Matching
1; Match expressions for control flow
2(match result
3 ["success" (handle-success)]
4 ["error" (handle-error)]
5 [_ (handle-unknown)])
6
7; Destructuring
8(match (cons key value)
9 [(cons k v) (process k v)])
Parsing and Generating XML with X-expressions
X-expressions (xexpr)
S-expression representation of XML:
1; xexpr format: (tag ((attr val) ...) child ...)
2(define doc
3 `(response
4 (status ((code "200")) "OK")
5 (data "content")))
6
7; Convert between formats
8(require xml)
9(xexpr->string doc) ; xexpr -> XML string
10(string->xexpr "<xml>...</xml>") ; XML string -> xexpr
11
12; Reading XML files
13(define xexpr
14 (string->xexpr
15 (if (bytes? param)
16 (bytes->string/utf-8 param)
17 param)))
Building XML Dynamically
1(define (make-xml-body #:title title #:content content)
2 `(document
3 (metadata
4 (title ,title)
5 (timestamp ,(current-time-string)))
6 (body
7 (section ,content))))
Making HTTP Requests
1(require net/http-easy)
2
3; POST request with headers
4(define response
5 (post url
6 #:headers (hash 'content-type "application/json")
7 #:data request-body))
8
9(define body (bytes->string/utf-8 (response-body response)))
10(define status (response-status-code response))
URL Operations
1(require net/url)
2
3(define url-struct (string->url "https://api.example.com/v1"))
4(url-host url-struct) ; Extract host
5(url-path url-struct) ; Extract path
Formatting Time and Dates (HTTP & ISO 8601)
Current Time Formatting
1(require srfi/19)
2
3; RFC 7231 HTTP date format
4(define (http-date-string)
5 (define date (time-utc->date (make-time 'time-utc 0 (current-seconds))))
6 (date->string date "~a, ~d ~b ~Y ~H:~M:~S GMT"))
7; => "Thu, 02 Oct 2025 14:30:45 GMT"
8
9; ISO 8601 date
10(date->string date "~Y-~m-~d")
11; => "2025-10-02"
Gotcha: Default parameter values are evaluated at call time:
1; CORRECT - fresh timestamp each call
2(define (timestamp [secs (current-seconds)])
3 (format-time secs))
4
5; WRONG - timestamp frozen at definition time in some contexts
Managing Configuration with Environment Variables
Reading Config
1; Simple read
2(getenv "API_KEY") ; => string or #f
3
4; With default value
5(define (get-config key [default #f])
6 (or (getenv key) default))
7
8; With error on missing
9(define (require-config key)
10 (or (getenv key)
11 (error 'config "Missing required env var: ~a" key)))
Environment-Based Behavior
1(define app-env (or (getenv "APP_ENV") "prod"))
2
3(define debug? (string=? "dev" app-env))
4(define prod? (string=? "prod" app-env))
5
6(when debug?
7 (displayln "Debug mode enabled"))
File I/O: Reading, Writing, and Paths
Reading Files
1(require racket/file)
2
3; Read entire file
4(file->string "/path/to/file.txt")
5(file->bytes "/path/to/file.bin")
6
7; Write file
8(write-to-file data path
9 #:mode 'text ; or 'binary
10 #:exists 'replace) ; or 'append, 'error, 'truncate
Path Operations
1(require racket/path)
2
3; Build paths safely
4(build-path "dir" "subdir" "file.txt")
5
6; System paths
7(find-system-path 'orig-dir) ; Original working directory
8(find-system-path 'temp-dir) ; Temp directory
Critical Gotcha: raco test changes the working directory:
1; WRONG - breaks in tests
2(define key-path "certs/key.pem")
3
4; CORRECT - use absolute paths
5(define key-path
6 (build-path (find-system-path 'orig-dir) "certs" "key.pem"))
Building a Command-Line Interface (CLI)
Argument Parsing
1(define file-param (make-parameter #f))
2(define id-param (make-parameter #f))
3
4(define cli
5 (command-line
6 #:program "app-name"
7 #:once-each
8 [("-f" "--file") path "Input file path"
9 (file-param path)]
10 [("-i" "--id") id "Record ID"
11 (id-param id)]
12 #:args (command)
13 command))
14
15; Use with match
16(match cli
17 ["process" (process-file (file-param))]
18 ["help" (display-help)]
19 [_ (error "Unknown command")])
Unit Testing with Rackunit
Basic Test Structure
1(module+ test
2 (require rackunit)
3
4 (test-case "description"
5 (check-equal? actual expected)
6 (check-true (predicate? value))
7 (check-exn exn:fail? (lambda () (failing-operation)))))
Test Suites
1(define my-tests
2 (test-suite
3 "Feature tests"
4 (test-case "case 1" ...)
5 (test-case "case 2" ...)))
6
7(run-tests my-tests)
Exception Testing
1; Test that function raises exception
2(check-exn exn:fail?
3 (lambda () (function-that-should-fail)))
4
5; Test specific error message
6(check-exn #rx"specific error"
7 (lambda () (failing-function)))
Common Pitfalls and How to Avoid Them
1. Multiple Return Values
1; WRONG - only captures first value
2(define response (http-request url))
3
4; CORRECT - captures all values
5(define-values (body status) (http-request url))
2. Bytes vs Strings
HTTP libraries often return bytes, XML functions expect strings:
1; Common pattern
2(define xml-data
3 (string->xexpr
4 (if (bytes? param)
5 (bytes->string/utf-8 param)
6 param)))
3. Parameter Default Values
1; Default evaluated at call time (good for timestamps)
2(define (log-message msg [time (current-seconds)])
3 ...)
4
5; Each call gets fresh timestamp
4. Working Directory in Tests
Tests run in different directory:
1; ALWAYS use absolute paths for file operations
2(define config-path
3 (build-path (find-system-path 'orig-dir) "config.json"))
Performance Optimization Techniques
1. Immutable vs Mutable
Prefer immutable data structures - they’re optimized:
1(make-immutable-hash alist) ; Preferred
2(make-hash alist) ; Only if mutation needed
2. List Comprehensions
Use for/list, for/hash for efficient collection building:
1; Build list
2(for/list ([item items])
3 (process item))
4
5; Build hash
6(for/hash ([pair pairs])
7 (values (car pair) (cdr pair)))
3. String Building
Use string-join instead of repeated string-append:
1; SLOW
2(foldl string-append "" string-list)
3
4; FAST
5(string-join string-list "")
Summary of Idiomatic Racket Best Practices
- Always use contracts for exported functions
- Test submodules for all library code
- Absolute paths for file operations
- define-values for multi-return functions
- Immutable data by default
- X-expressions for XML processing
- Parameters for CLI arguments
- Pattern matching over conditionals
Related Cheat Sheets
- Racket Cryptography - Hashing, digital signatures, key management, HTTP Message Signatures
- Racket Web Applications - Web servers, routing, request handling