#### 1.11S-Expression Matching

Since the equal? function works on any kind of value, it can compare two S-expressions to determine whether they are the same:

 > (equal? `{+ 1 2} `{+ 1 2}) - Boolean #t > (equal? `{+ 1 2} `{+ 1 4}) - Boolean #f

Suppose that you don’t just want to recognize `{+ 1 2}, but you want to recognize any list-like S-expression that has three elements where the first element is '+-like and the other two elements are number-like. That recognition problem is tedious to implement, due to the many required many checks and coercions.

 > (define (is-plus-numbers? se) (and (s-exp-list? se) (let ([l (s-exp->list se)]) (and (= 3 (length l)) (let ([a (first l)]) (and (s-exp-symbol? a) (eq? '+ (s-exp->symbol a)))) (s-exp-number? (second l)) (s-exp-number? (third l))))))
> (is-plus-numbers? `{+ 1 2})

- Boolean

#t

> (is-plus-numbers? `1)

- Boolean

#f

> (is-plus-numbers? `{+ 3 y})

- Boolean

#f

> (is-plus-numbers? `{{+} 1 2})

- Boolean

#f

The s-exp-match? function simplifies recognition tasks for S-expressions. It’s like equal? on S-expressions, but the first S-expression can have special symbols that match different classes of values, instead of matching themselves literally. The special symbols include NUMBER, which matchs any number, so is-plus-numbers? is more simply implemented like this:

 > (define (is-plus-numbers? se) (s-exp-match? `{+ NUMBER NUMBER} se))
> (is-plus-numbers? `{+ 1 2})

- Boolean

#t

> (is-plus-numbers? `{+ 3 y})

- Boolean

#f

Other special symbols include SYMBOL, which matches any symbol, and ANY, which matches anything.

 > (define (single-argument-lambda? se) (s-exp-match? `{lambda {SYMBOL} ANY} se))
> (single-argument-lambda? `{lambda {x} {+ x 1}})

- Boolean

#t

- Boolean

#f

The symbol ... is even more special. It causes the preceeding S-expression to match zero or more times to cover multiple elements in an enclosing list. For example, `{SYMBOL ...} would match a list-like S-expression that has any number of symbol-like elements.

 > (define (any-argument-lambda? se) (s-exp-match? `{lambda {SYMBOL ...} ANY} se))
> (any-argument-lambda? `{lambda {x} {+ x 1}})

- Boolean

#t

> (any-argument-lambda? `{lambda {x y z} {+ x 1}})

- Boolean

#t

> (any-argument-lambda? `{lambda {} {+ x 1}})

- Boolean

#t

- Boolean

#f