sigildocs

Chapter 4: Data Types

Sigil provides several built-in data types for organizing information.

Pairs

The most fundamental compound type is the pair, created with cons:

> (cons 1 2)
(1 . 2)

This creates a pair containing 1 and 2. The dot notation (1 . 2) shows it's a pair.

Access the elements with car and cdr:

> (car (cons 1 2))
1
> (cdr (cons 1 2))
2

These names come from early Lisp machines: "Contents of Address Register" and "Contents of Decrement Register."

Lists

A list is a chain of pairs ending in the empty list '():

> (cons 1 (cons 2 (cons 3 '())))
(1 2 3)

The list procedure is more convenient:

> (list 1 2 3)
(1 2 3)
> (list "a" "b" "c")
("a" "b" "c")
> (list 1 "two" #t)
(1 "two" #t)

Quoting also creates lists:

> '(1 2 3)
(1 2 3)
> '(a b c)
(a b c)

List Operations

> (car '(1 2 3))
1
> (cdr '(1 2 3))
(2 3)
> (length '(1 2 3 4 5))
5
> (append '(1 2) '(3 4))
(1 2 3 4)
> (reverse '(1 2 3))
(3 2 1)

List Predicates

> (null? '())
#t
> (null? '(1))
#f
> (pair? '(1 2))
#t
> (list? '(1 2 3))
#t

Accessing Elements

> (list-ref '(a b c d e) 0)
a
> (list-ref '(a b c d e) 2)
c

Shortcut accessors for nested structures:

> (define lst '((1 2) (3 4)))
> (car lst)
(1 2)
> (caar lst)        ; (car (car lst))
1
> (cadr lst)        ; (car (cdr lst))
(3 4)
> (caddr '(a b c))  ; (car (cdr (cdr lst)))
c

Vectors

Vectors provide O(1) indexed access:

> (vector 1 2 3)
#(1 2 3)
> (make-vector 5 0)
#(0 0 0 0 0)
> (vector-ref (vector 'a 'b 'c) 1)
b
> (vector-length (vector 1 2 3))
3

Vectors are mutable:

> (define v (vector 1 2 3))
> (vector-set! v 1 99)
> v
#(1 99 3)

Convert between lists and vectors:

> (list->vector '(1 2 3))
#(1 2 3)

Structs

Structs let you define custom data types with named fields.

(import (sigil struct))

(define-struct point
  (x)
  (y))

This creates:

  • point — constructor with keyword arguments
  • point? — predicate to test if a value is a point
  • point-x, point-y — accessors for each field

Creating Structs

Use keyword arguments to create instances:

(define p (point x: 3 y: 4))
(point-x p)  ; => 3
(point-y p)  ; => 4
(point? p)   ; => #t

Default Values

Fields can have defaults:

(define-struct rectangle
  (width)
  (height)
  (color default: "black"))

(define r (rectangle width: 100 height: 50))
(rectangle-color r)  ; => "black"

Copying with Changes

Create a modified copy using the constructor with an existing struct:

(define r2 (rectangle r color: "red"))
(rectangle-width r2)  ; => 100 (from r)
(rectangle-color r2)  ; => "red" (changed)

The original r is unchanged — structs are immutable.

Quasiquote

Quasiquote ( `) lets you build lists with some parts evaluated:

> (define x 10)
> `(1 2 ,x)
(1 2 10)

The , (unquote) evaluates x. Without it, you'd get the symbol:

> `(1 2 x)
(1 2 x)

Splice lists with ,@ (unquote-splicing):

> (define nums '(3 4 5))
> `(1 2 ,@nums 6)
(1 2 3 4 5 6)

This is especially useful for building code in macros.

Association Lists

Association lists (alists) are lists of pairs for key-value storage:

(define person
  '((name . "Alice")
    (age . 30)
    (city . "Boston")))

(assq 'name person)   ; => (name . "Alice")
(cdr (assq 'name person))  ; => "Alice"

assq uses eq? for comparison (fast, for symbols). assoc uses equal? (works for any keys).

Practical Example

Here's a small program using these types:

(import (sigil struct))

;; Define a struct for game items
(define-struct item
  (name)
  (description)
  (weight default: 1))

;; Create some items
(define sword (item name: "Sword"
                    description: "A sharp blade"
                    weight: 5))

(define key (item name: "Golden Key"
                  description: "Opens mysterious doors"))

;; Store items in a list
(define inventory (list sword key))

;; Function to describe inventory
(define (describe-inventory items)
  (for-each
    (lambda (it)
      (println "- ~a: ~a" (item-name it) (item-description it)))
    items))

(describe-inventory inventory)
;; Output:
;; - Sword: A sharp blade
;; - Golden Key: Opens mysterious doors

Practice Exercises

  1. Create a person struct with name, age, and email fields.
  2. Write a procedure that takes a list of numbers and returns a list of their squares.
  3. Build a simple phone book using an association list.

What's Next

With data types covered, let's explore control flow and pattern matching.

Next: Control Flow →