@c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. @c Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @c @c The pattern syntax is taken from the documentation available in @c Andrew K. Wright's implementation of `match.scm', which is in the @c public domain. See Guile before commit @c d967913f05301a35573c5d3f7217d0994bbb1016 (Thu Jun 17 2010) or @c . @c FIXME: This section is a bit rough on the edges. The introduction @c could be improved, e.g., by adding examples. @node Pattern Matching @section Pattern Matching @cindex pattern matching @cindex (ice-9 match) The @code{(ice-9 match)} module provides a @dfn{pattern matcher}, written by Alex Shinn, and compatible with Andrew K. Wright's pattern matcher found in many Scheme implementations. @cindex pattern variable A pattern matcher can match an object against several patterns and extract the elements that make it up. Patterns can represent any Scheme object: lists, strings, symbols, records, etc. They can optionally contain @dfn{pattern variables}. When a matching pattern is found, an expression associated with the pattern is evaluated, optionally with all pattern variables bound to the corresponding elements of the object: @example (let ((l '(hello (world)))) (match l ;; <- the input object (('hello (who)) ;; <- the pattern who))) ;; <- the expression evaluated upon matching @result{} world @end example In this example, list @var{l} matches the pattern @code{('hello (who))}, because it is a two-element list whose first element is the symbol @code{hello} and whose second element is a one-element list. Here @var{who} is a pattern variable. @code{match}, the pattern matcher, locally binds @var{who} to the value contained in this one-element list---i.e., the symbol @code{world}. An error would be raised if @var{l} did not match the pattern. The same object can be matched against a simpler pattern: @example (let ((l '(hello (world)))) (match l ((x y) (values x y)))) @result{} hello @result{} (world) @end example Here pattern @code{(x y)} matches any two-element list, regardless of the types of these elements. Pattern variables @var{x} and @var{y} are bound to, respectively, the first and second element of @var{l}. Patterns can be composed, and nested. For instance, @code{...} (ellipsis) means that the previous pattern may be matched zero or more times in a list: @example (match lst (((heads tails ...) ...) heads)) @end example @noindent This expression returns the first element of each list within @var{lst}. For proper lists of proper lists, it is equivalent to @code{(map car lst)}. However, it performs additional checks to make sure that @var{lst} and the lists therein are proper lists, as prescribed by the pattern, raising an error if they are not. Compared to hand-written code, pattern matching noticeably improves clarity and conciseness---no need to resort to series of @code{car} and @code{cdr} calls when matching lists, for instance. It also improves robustness, by making sure the input @emph{completely} matches the pattern---conversely, hand-written code often trades robustness for conciseness. And of course, @code{match} is a macro, and the code it expands to is just as efficient as equivalent hand-written code. The pattern matcher is defined as follows: @deffn {Scheme Syntax} match exp clause1 clause2 @dots{} Match object @var{exp} against the patterns in @var{clause1} @var{clause2} @dots{} in the order in which they appear. Return the value produced by the first matching clause. If no clause matches, throw an exception with key @code{match-error}. Each clause has the form @code{(pattern body1 body2 @dots{})}. Each @var{pattern} must follow the syntax described below. Each body is an arbitrary Scheme expression, possibly referring to pattern variables of @var{pattern}. @end deffn @c FIXME: Document other forms: @c @c exp ::= ... @c | (match exp clause ...) @c | (match-lambda clause ...) @c | (match-lambda* clause ...) @c | (match-let ((pat exp) ...) body) @c | (match-let* ((pat exp) ...) body) @c | (match-letrec ((pat exp) ...) body) @c | (match-define pat exp) @c @c clause ::= (pat body) | (pat => exp) The syntax and interpretation of patterns is as follows: @verbatim patterns: matches: pat ::= identifier anything, and binds identifier | _ anything | () the empty list | #t #t | #f #f | string a string | number a number | character a character | 'sexp an s-expression | 'symbol a symbol (special case of s-expr) | (pat_1 ... pat_n) list of n elements | (pat_1 ... pat_n . pat_{n+1}) list of n or more | (pat_1 ... pat_n pat_n+1 ooo) list of n or more, each element of remainder must match pat_n+1 | #(pat_1 ... pat_n) vector of n elements | #(pat_1 ... pat_n pat_n+1 ooo) vector of n or more, each element of remainder must match pat_n+1 | #&pat box | ($ record-name pat_1 ... pat_n) a record | (= field pat) a ``field'' of an object | (and pat_1 ... pat_n) if all of pat_1 thru pat_n match | (or pat_1 ... pat_n) if any of pat_1 thru pat_n match | (not pat_1 ... pat_n) if all pat_1 thru pat_n don't match | (? predicate pat_1 ... pat_n) if predicate true and all of pat_1 thru pat_n match | (set! identifier) anything, and binds setter | (get! identifier) anything, and binds getter | `qp a quasi-pattern | (identifier *** pat) matches pat in a tree and binds identifier to the path leading to the object that matches pat ooo ::= ... zero or more | ___ zero or more | ..1 1 or more quasi-patterns: matches: qp ::= () the empty list | #t #t | #f #f | string a string | number a number | character a character | identifier a symbol | (qp_1 ... qp_n) list of n elements | (qp_1 ... qp_n . qp_{n+1}) list of n or more | (qp_1 ... qp_n qp_n+1 ooo) list of n or more, each element of remainder must match qp_n+1 | #(qp_1 ... qp_n) vector of n elements | #(qp_1 ... qp_n qp_n+1 ooo) vector of n or more, each element of remainder must match qp_n+1 | #&qp box | ,pat a pattern | ,@pat a pattern @end verbatim The names @code{quote}, @code{quasiquote}, @code{unquote}, @code{unquote-splicing}, @code{?}, @code{_}, @code{$}, @code{and}, @code{or}, @code{not}, @code{set!}, @code{get!}, @code{...}, and @code{___} cannot be used as pattern variables. Here is a more complex example: @example (use-modules (srfi srfi-9)) (let () (define-record-type person (make-person name friends) person? (name person-name) (friends person-friends)) (letrec ((alice (make-person "Alice" (delay (list bob)))) (bob (make-person "Bob" (delay (list alice))))) (match alice (($ person name (= force (($ person "Bob")))) (list 'friend-of-bob name)) (_ #f)))) @result{} (friend-of-bob "Alice") @end example @noindent Here the @code{$} pattern is used to match a SRFI-9 record of type @var{person} containing two or more slots. The value of the first slot is bound to @var{name}. The @code{=} pattern is used to apply @code{force} on the second slot, and then checking that the result matches the given pattern. In other words, the complete pattern matches any @var{person} whose second slot is a promise that evaluates to a one-element list containing a @var{person} whose first slot is @code{"Bob"}. Please refer to the @code{ice-9/match.upstream.scm} file in your Guile installation for more details. Guile also comes with a pattern matcher specifically tailored to SXML trees, @xref{sxml-match}.