Pattern Matching
Pattern matching is a key feature of most modern functional programming languages since it allows clean and secure code to be written. Internally, ``pattern-matching forms'' should be translated (compiled) into cascades of ``elementary tests'' where code is made as efficient as possible, avoiding redundant tests; Bigloo's ``pattern matching compiler'' provides this. The technique used is described in details in [QueinnecGeffroy92], and the code generated can be considered optimal In the cases of pattern matching in lists and vectors, not in structures for the moment. due to the way this ``pattern compiler'' was obtained. The ``pattern language'' allows the expression of a wide variety of patterns, including:- Non-linear patterns: pattern variables can appear more than once, allowing comparison of subparts of the datum (through
- Recursive patterns on lists: for example, checking that the datum is a list of zero or more
- Pattern matching on lists as well as on vectors and structures, and record types.
eq?
)
a
s followed by zero or more
b
s.
Bigloo pattern matching facilities
Only two special forms are provided for this in Bigloo:match-case
and match-lambda
.
match-case key clause...bigloo syntax
The argument key may be any expression and each clause has the form(pattern s-expression...)Semantics: A
match-case
expression is evaluated as
follows. key is evaluated and the result is compared with each
successive pattern. If the pattern in some clause yields a match, then
the expressions in that clause are evaluated from left to right in an
environment where the pattern variables are bound to the corresponding
subparts of the datum, and the result of the last expression in that
clause is returned as the result of the match-case
expression.
If no pattern in any clause matches the datum, then, if there is an
else
clause, its expressions are evaluated and the result of the last
is the result of the whole match-case
expression; otherwise the result
of the match-case
expression is unspecified.
The equality predicate used is eq?
.
(match-case '(a b a) ((?x ?x) 'foo) ((?x ?- ?x) 'bar)) ⇒ bar
.keep
The following syntax is also available:
match-lambda clause...bigloo syntax
It expands into a lambda-expression expecting an argument which, once applied to an expression, behaves exactly like amatch-case
expression.
((match-lambda ((?x ?x) 'foo) ((?x ?- ?x) 'bar)) '(a b a)) ⇒ bar
.keep
The pattern language
The syntax for <pattern> is:<pattern> ⇒ Matches: <atom> the <atom>. | (Remark:kwote
<atom>) any expressioneq?
to<atom>
. | (and
<pat1> ... <patn>) if all of<pati>
match. | (or
<pat1> ... ...<patn>) if any of<pat1>
through<patn>
matches. | (not
<pat>) if<pat>
doesn't match. | (?
<predicate>) if<predicate>
is true. | (<pat1> ... <patn>) a list of n elements. Here,...
is a meta-character denoting a finite repetition of patterns. | <pat> ... a (possibly empty) repetition of<pat>
in a list. | #(<pat> ... <patn>) a vector of n elements. | #{<struct> <pat> ... } a structure. |?
<id> anything, and bindsid
as a variable. |?-
anything. |??-
any (possibly empty) repetition of anything in a list. |???-
any end of list.
and, or, not, check
and kwote
must be
quoted in order to be treated as literals. This is the only justification
for having the kwote
pattern since, by convention, any atom which is
not a keyword is quoted.
?-
matches any s-expra
matches the atom'a
.?a
matches any expression, and binds the variablea
to this expression.
(? integer?)
matches any integer(a (a b))
matches the only list'(a (a b))
.???-
can only appear at the end of a list, and always succeeds. For instance, - when occurring in a list,
??-
matches any sequence of anything: (a ...)
matches any list ofa
's, possibly empty.(?x ?x)
matches any list of length 2 whosecar
is eq to its ((and (not a) ?x) ?x)
matches any list of length 2 whose#(?- ?- ???-)
matches any vector whose length is at least 2.#{foo (?- . ?-) (? integer?)}
matches any structure or record
(a ???-)
is equivalent to (a . ?-)
.
(a ??- b)
matches any list whose car
is a
and last
car
is b
.
cadr
car
is not eq to 'a
but is eq to its cadr
foo
whose first and second fields are respectively a pair and an
integer. You can provide only the fields you want to test. The order is not
relevant.
??-
and ...
patterns can not appear
inside a vector, where you should use ???-
: For example,
#(a ??- b)
or #(a...)
are invalid patterns, whereas
#(a ???-)
is valid and matches any vector whose first element
is the atom a
.