Racket Pattern Matching

By Xah Lee. Date: . Last updated: .

first, Racket Start (Install, Setup)

2015-10-11 WARNING THIS IS WORK IN PROGRESS. IT'S ALL WRONG.

pattern matching

#lang racket

(match 2
  {1 'one}
  [2 'two]
  [3 'three])
#lang racket 

(match '(1 2)
  [(list 0 1) 'one]
  [(list 1 2) 'two])
;; 'two

(match '(1 . 2)
  [(list 1 2) 'list]
  [(cons 1 2) 'pair])
;; 'pair

(match #(1 2)
  [(list 1 2) 'list]
  [(vector 1 2) 'vector])
;; 'vector
#lang racket

(struct shoe (size color))
(struct hat (size style))

(match (hat 23 'bowler)
  [(shoe 10 'white) "bottom"]
  [(hat 23 'bowler) "top"])

;; "top"
#lang racket

(match '(1)
  [(list x) (+ x 1)]
  [(list x y) (+ x y)])
;; 2

(match '(1 2)
  [(list x) (+ x 1)]
  [(list x y) (+ x y)])
;; 3

_ is unnamed pattern.

#lang racket

(match '(1 2)
  [(list _ _) 7])
;; 7

ellipsis ... is repetition of previous item. Used inside list or vector.

#lang racket

(match '(1 1 1)
  [(list 1 ...) 'ones]
  [_ 'other])
;; 'ones

(match '(1 1 2)
  [(list 1 ...) 'ones]
  [_ 'other])
;; 'other

(match '(1 2 3 4)
  [(list 1 x ... 4) x])
;; '(2 3)

(match (list (list 23 'bowler) (list 22 'pork-pie))
  [(list (list sz styl) ...) sz])
;; '(23 22)
#lang racket

(match '((! 1) (! 2 2) (! 3 3 3))
  [(list (list '! x ...) ...) x])
;; '((1) (2 2) (3 3 3))

Forms like match-let and match-lambda support patterns in positions that otherwise must be identifiers. For example, match-let generalizes let to a destructing bind:

#lang racket

(match-let ([(list x y z) '(1 2 3)])
  (list z y x))
;; '(3 2 1)

define syntax rule

(define-syntax-rule pattern template)

#lang racket

(define-syntax-rule (swap x y)
  (let ([tmp x])
    (set! x y)
    (set! y tmp)))

;; this defines a “function” named “swap” that takes 2 args
;; by pattern matching

(let ([a 1]
      [b 2])
  (swap a b)
  (vector a b)
  )
; '#(2 1)
(define-syntax id
  (syntax-rules (literal-id …)
    [pattern template]
    …))

the “parameterize” is like a dynamic binding “let”.

(parameterize ([parameter-expr value-expr] …)
  body …)

racket syntax stuff

#lang racket

;; create a literal syntax object

(syntax (+ 1 2))

;; sample printed output
;; #<syntax:1:0 (+ 1 2)>

(syntax …) can be written as #'…

A syntax object that contains just a symbol is an identifier syntax object. Racket provides some additional operations specific to identifier syntax objects, including the identifier? operation to detect identifiers. Most notably, free-identifier=? determines whether two identifiers refer to the same binding:

#lang racket
#lang racket
#lang racket
#lang racket

(syntax->datum #'(+ 1 2))               ; '(+ 1 2)
(eval (syntax->datum #'(+ 1 2)))        ; 3
(eval '(+ 1 2))                         ; 3
#lang racket
(identifier? #'car)                     ; #t

(identifier? #'(+ 1 2))                 ; #f

(free-identifier=? #'car #'cdr)         ; #f

(free-identifier=? #'car #'car)         ; #t

(require (only-in racket/base [car also-car]))
(free-identifier=? #'car #'also-car)    ; #t

(free-identifier=? #'car
                   (let ([car 8])
                     #'car))
;; #f

Note: some examples are from the Racket official documentation at http://docs.racket-lang.org/guide/