          (not (atom? (first p)))
          (= (count (first p)) 2)
          (not (= (first (first p)) '?))
+         (resolve (first (first p)))
          ((resolve (first (first p))) (first s))
          (match5 (rest p) (rest s)))
         (do

  (is (not (match '(1 (2 nope) 3) '(1 (2 not really) 3)))))
(defn basic-pattern-match-test [match]
  (is (match '(1 (? x) 2) '(1 not-really 2)))
  (is (= 'not-really ('x (match '(1 (? x) 2) '(1 not-really 2))))))
(with-test
  (defn match2 [p s]
    (cond

        :else false))
    (if (match-helper p s) @variables false))
  (basic-match-test match5)
  (basic-pattern-match-test match5)
  (function-pattern-match-test match5))
(with-test
  (defn match
  "Note: ClojureScript doesn't have resolve so arbitrary predicates won't work there."
    [p s]
    (def variables (atom {}))
    (defn match-helper [p s]
      (cond
        ; (or (atom? p) (atom? s)) false
        (empty? p) (empty? s)
        (atom? (first p))
        (and (not (empty? s))
             (= (first p) (first s))
             (match-helper (rest p) (rest s)))
        ; complex patterns
        (and (not (empty? s))
             (= (first (first p)) '?))
        (when (match-helper (rest p) (rest s))
          (swap! variables (fn [vs] (assoc vs (second (first p)) (first s))))
          true)
        (= (first (first p)) '*)
        (cond
          (and (not (empty? s))
               (match-helper (rest p) (rest s)))
          (do
            (swap! variables (fn [vs] (assoc vs (second (first p)) (list (first s)))))
            true)
          (match-helper (rest p) s)
          (do
            (swap! variables (fn [vs] (assoc vs (second (first p)) (list))))
            true)
          (and (not (empty? s))
               (match-helper p (rest s)))
          (do
            (swap! variables (fn [vs] (assoc vs
                                             (second (first p)) 
                                             (cons (first s) (vs (second (first p)))))))
            true))
        (and
         (not (empty? s))
         (resolve (first (first p)))
         ((resolve (first (first p))) (first s))
         (match-helper (rest p) (rest s)))
        (do
          (swap! variables (fn [vs] (assoc vs (second (first p)) (first s))))
          true)
        :else false))
    (if (match-helper p s) @variables false))
  (basic-match-test match)
  (basic-pattern-match-test match)
  (function-pattern-match-test match))
(defn match-state
  "Note: ClojureScript doesn't have resolve so arbitrary predicates won't work there."
  [p s]
