manpagez: man pages & more
info guile
Home | html | info | man
[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ] Patterns

We have already seen some examples of patterns in the previous section: (unless condition exp ...), (my-or exp), and so on. A pattern is structured like the expression that it is to match. It can have nested structure as well, like (let ((var val) ...) exp exp* ...). Broadly speaking, patterns are made of lists, improper lists, vectors, identifiers, and datums. Users can match a sequence of patterns using the ellipsis (...).

Identifiers in a pattern are called literals if they are present in the syntax-rules literals list, and pattern variables otherwise. When building up the macro output, the expander replaces instances of a pattern variable in the template with the matched subexpression.

(define-syntax kwote
  (syntax-rules ()
    ((kwote exp)
     (quote exp))))
(kwote (foo . bar))
⇒ (foo . bar)

An improper list of patterns matches as rest arguments do:

(define-syntax let1
  (syntax-rules ()
    ((_ (var val) . exps)
     (let ((var val)) . exps))))

However this definition of let1 probably isn’t what you want, as the tail pattern exps will match non-lists, like (let1 (foo 'bar) . baz). So often instead of using improper lists as patterns, ellipsized patterns are better. Instances of a pattern variable in the template must be followed by an ellipsis.

(define-syntax let1
  (syntax-rules ()
    ((_ (var val) exp ...)
     (let ((var val)) exp ...))))

This let1 probably still doesn’t do what we want, because the body matches sequences of zero expressions, like (let1 (foo 'bar)). In this case we need to assert we have at least one body expression. A common idiom for this is to name the ellipsized pattern variable with an asterisk:

(define-syntax let1
  (syntax-rules ()
    ((_ (var val) exp exp* ...)
     (let ((var val)) exp exp* ...))))

A vector of patterns matches a vector whose contents match the patterns, including ellipsizing and tail patterns.

(define-syntax letv
  (syntax-rules ()
    ((_ #((var val) ...) exp exp* ...)
     (let ((var val) ...) exp exp* ...))))
(letv #((foo 'bar)) foo)
⇒ bar

Literals are used to match specific datums in an expression, like the use of => and else in cond expressions.

(define-syntax cond1
  (syntax-rules (=> else)
    ((cond1 test => fun)
     (let ((exp test))
       (if exp (fun exp) #f)))
    ((cond1 test exp exp* ...)
     (if test (begin exp exp* ...)))
    ((cond1 else exp exp* ...)
     (begin exp exp* ...))))

(define (square x) (* x x))
(cond1 10 => square)
⇒ 100
(let ((=> #t))
  (cond1 10 => square))
⇒ #<procedure square (x)>

A literal matches an input expression if the input expression is an identifier with the same name as the literal, and both are unbound(11).

If a pattern is not a list, vector, or an identifier, it matches as a literal, with equal?.

(define-syntax define-matcher-macro
  (syntax-rules ()
    ((_ name lit)
     (define-syntax name
       (syntax-rules ()
        ((_ lit) #t)
        ((_ else) #f))))))

(define-matcher-macro is-literal-foo? "foo")

(is-literal-foo? "foo")
⇒ #t
(is-literal-foo? "bar")
⇒ #f
(let ((foo "foo"))
  (is-literal-foo? foo))
⇒ #f

The last example indicates that matching happens at expansion-time, not at run-time.

Syntax-rules macros are always used as (macro . args), and the macro will always be a symbol. Correspondingly, a syntax-rules pattern must be a list (proper or improper), and the first pattern in that list must be an identifier. Incidentally it can be any identifier – it doesn’t have to actually be the name of the macro. Thus the following three are equivalent:

(define-syntax when
  (syntax-rules ()
    ((when c e ...)
     (if c (begin e ...)))))

(define-syntax when
  (syntax-rules ()
    ((_ c e ...)
     (if c (begin e ...)))))

(define-syntax when
  (syntax-rules ()
    ((something-else-entirely c e ...)
     (if c (begin e ...)))))

For clarity, use one of the first two variants. Also note that since the pattern variable will always match the macro itself (e.g., cond1), it is actually left unbound in the template.

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated on April 20, 2013 using texi2html 5.0.

© 2000-2019
Individual documents may contain additional copyright information.