AtlatestRepositorysigil-web-styles
1
2# Idioms
3
4> Common patterns and best practices for idiomatic Sigil code.
5
6## Output
7
8Use `print`/`println` with format strings, not `display`/`newline`:
9
10```scheme
11;; Idiomatic
12(println "Hello, ~a!" name)
13(println "Got ~a items" (length items))
15;; Avoid (R7RS compatibility only)
16(display "Hello, ") (display name) (newline)
17```
19## Threading Pipelines
21Use `->` for data transformation pipelines instead of nested calls:
23```scheme
24;; Idiomatic - reads top to bottom
25(-> data
26 (filter positive? _)
27 (map square _)
28 (take 10 _))
30;; Avoid - reads inside out
31(take 10 (map square (filter positive? data)))
32```
34The `_` placeholder marks where the threaded value goes. Use `some->` for nil-short-circuiting:
36```scheme
37(some-> user
38 (dict-ref _ email:)
39 validate-email
40 send-confirmation) ; stops if any step returns #f
41```
43## Pattern Matching
45Use `match` for type/shape dispatch instead of nested `cond`:
47```scheme
48(match cmd
49 (('add x y) (+ x y))
50 (('quit) (exit 0))
51 ((? string? s) (parse-string s))
52 (_ (error "Unknown command")))
53```
55Use `match-lambda` for inline match functions:
57```scheme
58(map (match-lambda
59 ((name . value) (format "~a=~a" name value)))
60 alist)
61```
63Use `match-let` for destructuring binds:
65```scheme
66(match-let (((x y) point)
67 ((w h) size))
68 (* (+ x w) (+ y h)))
69```
71## Polymorphic Collections
73Import `(sigil seq)` for operations that work on lists, vectors, arrays, and dicts:
75```scheme
76(import (sigil seq))
78(map square '(1 2 3)) ; => (1 4 9)
79(map square #(1 2 3)) ; => #(1 4 9)
80(filter even? #(1 2 3 4)) ; => #(2 4)
81(fold + 0 '(1 2 3 4)) ; => 10
82```
84## Transducers
86For complex transformations, compose transducers:
88```scheme
89(import (sigil seq))
91(define xform
92 (comp (filtering even?)
93 (mapping square)
94 (taking 5)))
96(sequence xform (iota 100)) ; => (0 4 16 36 64)
97(into #() xform '(1 2 3 4)) ; => #(4 16)
98```
100## Function Composition
102Import `(sigil fn)` for point-free style:
104```scheme
105(import (sigil fn))
107(define add1 (partial + 1))
108(define process (pipe string-trim string-upcase))
109(filter (complement null?) items)
110```
112## Higher-Order Functions
114Prefer HOFs over manual recursion:
116```scheme
117;; Good
118(filter even? numbers)
119(map string-upcase names)
120(fold + 0 values)
121(filter-map maybe-transform items)
123;; Avoid manual recursion for simple cases
124```
126Use named `let` for complex loops:
128```scheme
129(let loop ((items items) (acc '()))
130 (cond
131 ((null? items) (reverse acc))
132 ((valid? (car items))
133 (loop (cdr items) (cons (transform (car items)) acc)))
134 (else (loop (cdr items) acc))))
135```
137## Dicts
139Prefer dicts over alists for data:
141```scheme
142(define config
143 #{ host: "localhost"
144 port: 8080
145 debug: #f })
147(dict-ref config port:) ; => 8080
148(dict-set config debug: #t) ; => new dict
149(dict-merge defaults user-config) ; => merged dict
150```
152Use `dict-get-in` for nested access:
154```scheme
155(dict-get-in response '(body: data: items:))
156```
158## Keyword Arguments
160Use keywords for optional parameters:
162```scheme
163(define (connect host (keys: (port 80) (timeout 30)))
164 ...)
166(connect "localhost")
167(connect "localhost" port: 443 timeout: 60)
168```
170## Error Handling
172Use `guard` for expected errors:
174```scheme
175(guard (e ((file-error? e) #f))
176 (read-file-string path))
177```
179Use `error` for unexpected conditions:
181```scheme
182(unless user
183 (error "User not found: ~a" id))
184```
186## Boolean Expressions
188Use `and`/`or` for short-circuit logic:
190```scheme
191(or (find-cached key) (compute-value key))
192(and (valid? x) (authorized? user) (process x))
193```
195Avoid redundant boolean conversion:
197```scheme
198;; Good
199(not (null? items))
201;; Bad
202(if (not (null? items)) #t #f)
203```
205## Multi-List Operations
207For iterating multiple lists together, use `(sigil list)`:
209```scheme
210(import (sigil list))
212(list-map + '(1 2 3) '(10 20 30)) ; => (11 22 33)
213(list-fold (lambda (a b acc) (cons (+ a b) acc))
214 '() '(1 2) '(10 20)) ; => (22 11)
215```
217## Module Organization
219```scheme
220(define-library (myapp feature)
221 (import (sigil string))
222 (export public-api)
223 (begin
224 ;; Private helpers first
225 (define (helper x) ...)
227 ;; Public API
228 (define (public-api x)
229 (helper x))))
230```