A Primer on Guile Match Expressions

Notes

  • Match expressions are useful for destructuring information
  • The match expression is not standard in Scheme, it’s based on a paper by Andrew K. Wright
  • The (ice-9 match) module in Guile is based on a match implementation by Alex Shinn

Examples

match

(use-modules (ice-9 match))

(match '(1 2 3)
  ((x y z)
   (format #f "y is ~a" y)))

(match '(1 (2 3) 4)
  ((x (y z) foo)
   (format #f "z is ~a" z)))

(match '(1 2 3)
  ((1 y z)
   (format #f "y is ~a" y))
  (_ "Did not match!"))

(match '(3 2 1)
  ((1 y z)
   (format #f "y is ~a" y))
  (_ "Did not match!"))

(match '(3 2 1)
  ((1 y z)
   (format #f "y is ~a" y))
  ((a b) ;; List length does not match!
   (format #f "b is ~a" b))
  (_ "Did not match!"))

(match '(3 2 1)
  ((1 y z)
   (format #f "y is ~a" y))
  ((a b c)
   (format #f "b is ~a" b))
  (_ "Did not match!"))

(match '(3 2 1)
  ((or (1 y z)
       (x y z))
   (format #f "y is ~a" y))
  (_ "Did not match!"))

(match '(3 2 1)
  ((and (1 y z)
        (x y z))
   (format #f "y is ~a" y))
  (_ "Did not match!"))

(match '(1 2 3)
  ((and (1 y z)
        (x y z))
   (format #f "y is ~a" y))
  (_ "Did not match!"))

(match '(1 2 3)
  ((first . rest)
   (format #f "First item is ~a and rest is ~a." first rest))
  (_ "Did not match!"))

(let loop ((items '(1 2 3 4 5))
           (strings '()))
  (match items
    ((item . rest)
     (loop rest
           (cons (format #f "Item ~a" item)
                 strings)))
    (() (reverse strings))))

(let loop ((items '(1 2 3 4 5))
           (strings '()))
  (if (pair? items)
      (loop (cdr items)
            (cons (format #f "Item ~a" (car items))
                  strings))
      (reverse strings)))

(match '(1 2 3)
  ((numbers ...)
   (format #f "Here are some numbers: ~a" numbers))
  (_ "Did not match!"))

(match #(1 2 3)
  ((x y z)
   "It's a list!")
  (#(x y z)
   (format #f "y is ~a" y))
  (_ "Did not match!"))

(use-modules (srfi srfi-9))

(define-record-type person
  (make-person name age hometown)
  person?
  (name person-name)
  (age person-age)
  (hometown person-hometown))

(match (make-person "David" 132 "Mars")
  (($ person name age hometown)
   (format #f "~a is ~a and from ~a." name age hometown))
  (_ "Not a record of 'person'!"))

(match (make-person "David" 132 "Mars")
  ((= person-age 50)
   "The person is 50 years old.")
  (_ "Not 50 years old!"))

(match (make-person "David" 50 "Mars")
  ((= person-age 50)
   "The person is 50 years old.")
  (_ "Not 50 years old!"))

(match (make-person "David" 50 "Mars")
  ((? person? person)
   (format #f "The person is ~a years old." (person-age person)))
  (_ "Not 50 years old!"))

match-lambda and match-lambda*

(match '(1 2 3)
  ((and (1 y z)
        (x y z))
   (format #f "y is ~a" y))
  (_ "Did not match!"))

(define match-numbers
  (match-lambda
    ((and (1 y z)
          (x y z))
     (format #f "y is ~a" y))
    (_ "Did not match!")))

(match-numbers '(1 2 3))
(match-numbers '(3 2 1))

(define match-numbers*
  (match-lambda*
    ((and (1 y z)
          (x y z))
     (format #f "y is ~a" y))
    (_ "Did not match!")))

(match-numbers* 1 2 3)
(match-numbers* 3 2 1)

match-let

(define my-values '(1 (1 2) 3))

(match-let (((x y z) my-values))
   (format #f "y is ~a" y))

(match-let (((x (a b) z) my-values))
   (format #f "b is ~a" b))

(match-let* (((x y z) my-values)
             ((a b) y))
   (format #f "b is ~a" b))

(match-let loop (((or (item . rest)
                      _)
                  '(1 2 3 4 5))
                 (strings '()))
  (if (null? item)
      strings
      (loop rest
            (cons (format #f "Item ~a" item)
                  strings))))

Also match-let* and match-letrec

Community-Contributed Examples

Contribute your own examples by submitting a pull request to the repository on Codeberg!

Subscribe to the System Crafters Newsletter!
Stay up to date with the latest System Crafters news and updates! Read the Newsletter page for more information.
Name (optional)
Email Address