Racket Pattern Matching
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/