#lang racket

(define (map f lst)
  (match lst
    ['() '()]
    [(cons x xs) (cons (f x)
                       (map f xs))]))

(define (filter pred lst)
  (match lst
    [(cons x xs) #:when (pred x)
                 (cons x (filter pred xs))]
    [(cons _ xs) (filter pred xs)]
    ['() '()]))


(struct shoe (size color))
(struct hat (size style))
(match (hat 23 'bowler)
   [(shoe 10 'white) "bottom"]
   [(hat 23 'bowler) "top"])
;  "top"


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

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

(match '(1 2 (3 4) 5)
  [`(1 ,(? even? x) ,y 5) (cons x y)])

(define-match-expander aba?
  (lambda (stx)
    (syntax-case stx ()
      [(aba? a b)
       #'(list a b a)])))

(match (list 1 2 1)
  [(aba? 1 2) 'worked])