(sigil struct)
(sigil struct) - Struct Types
Provides define-struct for creating named-field data structures with:
- Keyword-based construction
- Optional field defaults
- Optional per-field mutability
- Optional field type annotations for procedure specs
- Struct embedding via
include:
Basic Usage
(import (sigil struct))
(define-struct person
(name default: "")
(age default: 0))
;; Constructor uses type name with keywords:
(define alice (person name: "Alice" age: 30))
;; Accessors use typename-fieldname:
(person-name alice) ; => "Alice"
(person-age alice) ; => 30
;; Predicate:
(person? alice) ; => #tMutable Fields
Fields are immutable by default. Use mutable: #t for mutability:
(define-struct counter
(value default: 0 mutable: #t))
(define c (counter))
(set-counter-value! c 10)
(counter-value c) ; => 10Copy-Construction
Pass an existing struct as the first argument to copy with modifications:
(define alice (person name: "Alice" age: 30))
(define bob (person alice name: "Bob"))
;; bob has name: "Bob", age: 30Field Type Annotations
Fields can have type predicates for automatic procedure spec generation:
(define-struct point
(x number?)
(y number?))
(procedure-spec point-x) ; => (point? -> number?)
(procedure-spec point) ; => ((x: number?) (y: number?) -> point?)Type predicates go after the field name, before keyword options:
(define-struct counter
(value number? default: 0 mutable: #t))Struct Embedding
Use include: to embed another struct's fields:
(define-struct employee
include: person
(department default: "Engineering")
(salary))
(define emp (employee name: "Alice" age: 30 department: "Eng" salary: 80000))
(employee-name emp) ; => "Alice" (inherited field)
(employee-department emp) ; => "Eng" (own field)
(employee->person emp) ; => #<person name: "Alice" age: 30>Exports
struct?procedureTest if a value is a struct instance.
(struct? (person name: "Alice")) ; => #t
(struct? '(1 2 3)) ; => #fstruct-type?procedureTest if a value is a struct type descriptor.
(struct-type? (struct-type-of my-struct)) ; => #tstruct-type-ofprocedureGet the struct type descriptor from a struct instance.
(struct-type-of (person name: "Alice"))
; => #<struct-type person>struct-type-nameprocedureGet the name of a struct type as a symbol.
(struct-type-name (struct-type-of p)) ; => personstruct-type-field-countprocedureGet the number of fields in a struct type (including inherited).
(struct-type-field-count (struct-type-of p)) ; => 2struct-type-field-namesprocedureGet the field names of a struct type as an array.
(struct-type-field-names (struct-type-of p)) ; => #(name age)struct-type-parentprocedureGet the parent struct type, or #f if none.
(struct-type-parent (struct-type-of emp))
; => #<struct-type person>struct-field-indexprocedureGet the field index for a given field name in a struct type.
Returns the zero-based index, or #f if the field doesn't exist.
(struct-field-index (struct-type-of p) 'name) ; => 0
(struct-field-index (struct-type-of p) 'age) ; => 1%struct-registryvariableTracks struct type metadata during compilation so that child structs can generate inherited accessors. The registry: maps type-name symbol to (field-names parent-type) Uses a mutable list so it persists across macro expansions
%register-struct-type!procedureRegister a struct type's metadata field-types is a list of type predicates (symbols or #f) parallel to field-names
%collect-fields-from-typeprocedureCollect all fields from a struct-type object by walking parent chain
%lookup-imported-struct-typeprocedureTry to look up a struct type from imported modules Looks up the constructor and extracts the type from its metadata. Returns (all-field-names #f all-field-types) or #f if not found Note: Returns #f for parent since we've already collected all fields
%collect-field-types-from-metaprocedureCollect field types from constructor metadata Returns a list of type predicates (symbols or #f) for all fields
%lookup-struct-typeprocedureLook up a struct type's metadata First checks local registry, then falls back to imported types Returns (field-names parent-type field-types) or #f if not found
%get-inherited-fieldsprocedureGet all field names from a type (own + inherited). Walks the parent chain via procedure metadata.
%get-inherited-field-typesprocedureGet all field types from a type (own + inherited). Walks the parent chain, parallel to %get-inherited-fields.
%no-defaultvariableSentinel for "no default provided" (required field)
struct--unwrapprocedureHelper: Unwrap syntax object to get datum
struct--get-docprocedureHelper: Get docstring from syntax object
struct--get-srclocprocedureHelper: Get srcloc from syntax object
parse-field-specprocedureHelper: Process field spec into (name default mutable? docstring type-pred)
type-pred is a symbol like number? or #f if no type annotation. Type predicates appear after the field name and before keyword options: (x number? default: 0 mutable: #t)
make-accessorprocedureHelper: Build accessor definition with docstring
make-mutatorprocedureHelper: Build mutator definition with auto-generated docstring
struct-transformerprocedureThe define-struct macro transformer
define-structsyntaxDefine a struct type with named fields.
Creates a constructor, predicate, and field accessors for a new struct type. Fields can have defaults (default:), be mutable (mutable: #t), and structs can embed other structs (include:).
(define-struct person
(name default: "")
(age default: 0 mutable: #t))
(define p (person name: "Alice" age: 30))
(person-name p) ; => "Alice"
(set-person-age! p 31)