When this matters
Choose the smallest value shape that communicates the job. Use an atom for one fact, a proper list for sequential data, a vector for indexed mutable slots, or a bytevector for a fixed-length block of bytes.
See it run
(list (vector? #(1 2)) (bytevector? #u8(1 2)) (pair? (cons 1 2)))Observed result
(#t #t #t)Read the example
The example asks three predicates about three different aggregate values. Each constructor creates the documented kind of value, so the result is a list of three true booleans.
cons joins two values into one pair. Put a list on the right and the list grows by one, so (cons 1 (list 2 3)) is (1 2 3). Put anything else there and you get a pair that is not a list, so (cons 1 2) is (1 . 2). pair? is the question of whether a value is that pair.
When the shape is mostly fixed and only a few slots need filling, use quasiquote. Write the template after a backtick and put a comma where a value goes. One comma drops a single value into that slot, and ,@ opens a list out across several slots.
(define x 7)
(define ys (list 2 3))
`(a ,x ,@ys b)Observed result
(a 7 2 3 b),@ only works where list elements go. Alone anywhere else it is E130.
How to reason about it
- Pairs, strings, and bytevectors are immutable in the current profile, while vectors and lexical cells are mutable.
- Quoted aggregate data is immutable, and constructors create runtime aggregates with the documented identity rules.
- Improper and cyclic structures are distinguished from proper lists, and deep equality terminates on cycles.
Choose quickly
| Value family | Typical spelling | Mutation in the current profile |
|---|---|---|
| atoms | #t, 42, 2/3, name, #\\a | not applicable |
| list / pair | (list 1 2), (cons 1 2) | immutable |
| string | "hello" | immutable |
| vector | #(1 2) or (vector 1 2) | mutable slots |
| bytevector | #u8(1 2) | immutable |
| procedure | (lambda (x) x) | a callable value whose body is not data |
A common mistake
Complex numbers, ports, records, and mutable pairs or strings are outside the current profile.
Current boundaries
- Internal outcomes, signals, and internal markers for uninitialized cells are not guest values.
Keep going
List and Aggregate Procedures gives constructors and accessors. Equality explains identity versus structural comparison.