Up: simple-match [Index]
The following bindings are exported by the library (vicare
languae-extensions simple-match)
. The auxiliary syntaxes are the
bindings exported by the library (vicare)
, which are reexported
by this library.
Match the symbolic expression ?expr against the ?clause arguments. Each clause must have one of the formats:
(?pattern ?body ...) (?pattern (=> ?next) ?body ...) (else ?body0 ?body ...)
?expr is evaluated once and the result is matched against each
?pattern in turn; the first to succeed causes the corresponding
?body forms to be evaluated as in begin
, and the remaining
patterns are ignored. However, if the ?next identifier is
labeled, it may be used as a continuation to continue matching, allowing
for additional runtime tests on the pattern.
A clause with no body (?pattern)
, when matching the input
expression, causes the evaluation of (values)
(which returns zero
values).
The syntax for the patterns is:
The literal underscore is the wildcard: it matches anything, it does not reference any variable.
(match "ciao" (_ #t) (else #f)) ⇒ #t (match '(1 2 3) (_ #t) (else #f)) ⇒ #t (match '(1 2 3) ((_ _ _) #t) (else #f)) ⇒ #t (match '(1 2 3) ((_ 2 _) #t) (else #f)) ⇒ #t (match '(1 2 3) ((_ 0 _) #t) (else #f)) ⇒ #f
Matches if the input expression equals ?datum. The pattern ?datum can be a boolean, character, fixnum, bignum, ratnum, flonum, cflonum, compnum, string or bytevector; such data is compared to the input expression using type–specific predicates and unsafe accessors.
(match 1 (1 #t) (else #f)) ⇒ #t
Variable reference: it matches the value bound to ?variable using
equal?
.
(let ((X 1)) (match 1 (X #t) (else #f))) ⇒ #t (let ((X 1)) (match 1 (X X) (else #f))) ⇒ 1
Bind the value of the input expression to ?variable, which must be
an identifier; the variable is immediately available to be referenced in
the following subpatterns. The empty let
pattern is a syntax
error; the let
pattern with multiple subpatterns is a syntax
error, with the exception of the variable with ellipsis.
(match 1 ((let X) X) (else #f)) ⇒ 1 (match 1 ((let X) #\A) (else #f)) ⇒ #\A (match '(1) ((let X) X) (else #f)) ⇒ (1) (match '(1) (((let X)) X) (else #f)) ⇒ 1 (match '(1 2 3) (((let X) (let Y) (let Z)) (vector X Y Z)) (else #f)) ⇒ #(1 2 3) (match '(1 2) (((let X) (let Y) (let Z)) (vector X Y Z)) (else #f)) ⇒ #f (match '(1 (2 3)) (((let X) (let X) (let X)) X) (else #f)) ⇒ 3 (match 123 ((and (let X) (eval (positive? X))) X) (else #f)) ⇒ 123 (match '(1 2 3) (((and (apply number?) (let N1)) . (and (apply (lambda (obj) (for-all number? obj))) (let N))) (vector N1 N)) (else #f)) ⇒ #(1 (2 3))
This pattern can appear only as last subpattern of a list or vector pattern. Bind the rest of the input expression to ?variable, which must be an identifier, as a list; the variable is immediately available to be referenced in the following subpatterns.
(match '(1 2 3 4 5) (((let X) (let Y) (let Z ...)) (vector X Y Z)) (else #f)) ⇒ #(1 2 (3 4 5)) (match '(1 2) (((let X) (let Y) (let Z ...)) (vector X Y Z)) (else #f)) ⇒ #(1 2 ()) (match '(1 2 . 3) (((let X) (let Y) (let Z ...)) (vector X Y Z)) (else #f)) ⇒ #f (match '(1 2 3 4 . 5) (((let X) (let Y) (let Z ...)) (vector X Y Z)) (else #f)) ⇒ #f (match '(1 2 3) ((let id ...) #\A) (else #\B)) error→ &syntax (match '(1 2 3 4) (((and (apply number?) (let N1)) (and (apply number?) (let N)) ...) (vector N1 N)) (else #f)) ⇒ (#(1 2) #(1 3) #(1 4))
A quoted datum; it matches if it is equal to the input expression
according to equal?
. As special case: if ?datum is a
symbol, it is compared to the input expression with eq?
.
(match '(1 2 3) ('(1 2 3) #t) (else #f)) ⇒ #t (match '(1 X 3) ('(1 X 3) #t) (else #f)) ⇒ #t (match '(1 X 3) ((1 'X 3) #t) (else #f)) ⇒ #t
A quasiquoted datum; it matches if it the result of the quasiquotation
is equal to the input expression according to equal?
.
(let ((X 2)) (match '(2 2) (`(1 ,X) #\A) (`(2 ,X) #\B) (`(3 ,X) #\C) (else #f))) ⇒ #\B
A syntax-case
pattern with optional literal identifiers; the
matching code is built as follows:
(syntax-case input-expr (?literal …) (?pattern #;success) (_ #;failure))
the body of the clause can access pattern variables in the same way they
are accessed from the output expression of a syntax-case
use.
(match '(1 2 3) ((syntax (1 2 3)) #t) (else #f)) ⇒ #t ;;match an identifier (let ((ciao #f)) (match #'ciao ((syntax ciao (ciao)) #t) (else #f))) ⇒ #t ;;match pattern variables (let ((ciao #f)) (match '(1 2 3) ((syntax (a b c)) (syntax->datum #'b)) (else #f))) ⇒ 2
Null or proper list of N elements.
(match '() (() #t) (else #f)) ⇒ #t (match '(1 2 3) ((1 2 3) #t) (else #f)) ⇒ #t
Improper list of N or more elements.
(match '(1 . 2) ((1 . 2) #t) (else #f)) ⇒ #t (match '(1 2 3 . 4) ((1 2 3 . 4) #t) (else #f)) ⇒ #t
List of N or more elements with terminating ellipsis; each element of remainder must match ?patternN+1. The body is evaluated once for every element matched by the pattern before the ellipsis and the results are returned in a list.
(match '(1) ((1 ...) #t) (else #f)) ⇒ (#t) (match '(1 1) ((1 ...) #t) (else #f)) ⇒ (#t #t) (match '(1 1 1) ((1 ...) #t) (else #f)) ⇒ (#t #t #t) (match '(1 2) ((0 1 ...) #t) (else #f)) ⇒ #f (match '(1 2 3) (((let X) ...) (+ 10 X)) (else #f)) ⇒ (11 12 13) (match '(1 2 3) (((let X) (let Y) ...) (vector X Y)) (else #f)) ⇒ (#(1 2) #(1 3)) (match '((1 2 3) (4 5 6) (7 8 9)) ((((let X) (let Y) (let Z)) ...) (vector X Y Z)) (else #f)) ⇒ (#(1 2 3) #(4 5 6) #(7 8 9)) (match '((1 2 3) (4 5 6) (7 8 9)) ((((let X) (let Y) ...) ...) (vector X Y)) (else #f)) ⇒ ((#(1 2) #(1 3)) (#(4 5) #(4 6)) (#(7 8) #(7 9)))
Vector of N elements.
(match '#(1 2 3) (#(1 2 3) #t) (else #f)) ⇒ #t
Vector of N or more elements with terminating ellipsis; each element of remainder must match ?patternN+1. The body is evaluated once for every element matched by the pattern before the ellipsis and the results are returned in a list.
(match '#(1 1 1) (#(1 ...) #t) (else #f)) ⇒ (#t #t #t)
Matches if each ?pattern matches the input expression. The empty
and
succeeds.
(match 123 ((and (apply fixnum?) (apply positive?)) #t) (else #f)) ⇒ #t (match 123 ((and (apply fixnum?) (let X)) X) (else #f)) ⇒ 123 (match 123 ((and (let X) X) X) (else #f)) ⇒ 123
Matches if at least one ?pattern matches the input expression.
The empty or
fails.
(match 1 ((or 1 2) #t) (else #f)) ⇒ #t (match 1 ((or (apply fixnum?) (apply bignum?)) #t) (else #f)) ⇒ #t
Matches if the subpattern ?pattern does not match the
input expression. The empty not fails. The empty not
pattern is
a syntax error; the not
pattern with multiple subpatterns is a
syntax error.
(match 9 ((not 1) #t) (else #f)) ⇒ #t (match "ciao" ((not (apply fixnum?)) #t) (else #f)) ⇒ #t
Each ?pred subpattern must be an expression; every time this
pattern is matched against an input expression: ?pred is
evaluated; the value returned by ?pred must be a predicate
function. This pattern matches if all the predicate functions return
true when applied to the input expression; the empty apply
pattern is a syntax error.
(match 1 ((apply fixnum? positive?) #t) (else #f)) ⇒ #t (match 1 ((apply (lambda (x) (and (fixnum? x) (positive? x)))) #t) (else #f)) ⇒ #t
The subpattern ?expr must be expression; every time this pattern
is matched against an input expression: ?expr is evaluated. This
pattern matches if the result of ?expr is true. The empty
eval
pattern is a syntax error; the eval
pattern with
multiple subpatterns is a syntax error.
(match 1 ((eval #t) #t) (else #f)) ⇒ #t (match 1 ((eval #f) #\A) (else #f)) ⇒ #t (match #t ((and (let X) (eval X)) #t) (else #f)) ⇒ #t (match #f ((and (let X) (eval X)) #t) (else #f)) ⇒ #f (match '(1 2) (((let X) (eval X)) ;ignores 2, but consumes it X) (else #f)) ⇒ 1 (match '(1 2 3) (((let X) (eval X) (let Y)) ;ignores 2, but consumes it (vector X Y)) (else #f)) ⇒ #(1 3)
When the escape identifier is present, it is bound to a thunk to be evaluated to jump to matching the next pattern or to the “no match” error.
(match '(1 2 3) ((1 2 3) (=> escape) #t) (else #f)) ⇒ #t (match '(1 2 0) ((1 2 3) (=> escape) #t) (else #f)) ⇒ #f (match '(1 2 3) ((1 2 3) (=> escape) (escape)) (else #f)) ⇒ #f (match '(1 2 3) ((1 2 3) (=> escape) (escape)) ((1 2 3) #t) (else #f)) ⇒ #t (match '(1 2 3) ((1 2 3) (=> escape) (escape))) error→ &error
Up: simple-match [Index]