match docs
svn: r7817
This commit is contained in:
parent
27f7f770b8
commit
44478fa8e0
|
@ -12,21 +12,21 @@
|
||||||
;;!(function setter
|
;;!(function setter
|
||||||
;; (form (setter e ident let-bound) -> syntax)
|
;; (form (setter e ident let-bound) -> syntax)
|
||||||
;; (contract (syntax syntax list) -> syntax)
|
;; (contract (syntax syntax list) -> syntax)
|
||||||
;; (example (setter (syntax (car x)) (syntax here) '())
|
;; (example (setter (syntax (mcar x)) (syntax here) '())
|
||||||
;; ->
|
;; ->
|
||||||
;; (syntax (lambda (y) (set-car! x y)))))
|
;; (syntax (lambda (y) (set-mcar! x y)))))
|
||||||
;; This function takes an expression and returns syntax which
|
;; This function takes an expression and returns syntax which
|
||||||
;; represents a function that is able to set the value that the
|
;; represents a function that is able to set the value that the
|
||||||
;; expression points to.
|
;; expression points to.
|
||||||
(define (setter e ident let-bound)
|
(define (setter e ident let-bound)
|
||||||
(define (subst e) (subst-bindings e let-bound))
|
(define (subst e) (subst-bindings e let-bound))
|
||||||
(define (mk-setter s cxt) (datum->syntax-object cxt (symbol-append 'set- s '!)))
|
(define (mk-setter s cxt) (datum->syntax-object cxt (symbol-append 'set- s '!)))
|
||||||
(syntax-case e (vector-ref unbox car cdr)
|
(syntax-case e (vector-ref unbox car cdr mcar mcdr)
|
||||||
[p
|
[p
|
||||||
(not (stx-pair? #'p))
|
(not (stx-pair? #'p))
|
||||||
(match:syntax-err
|
(match:syntax-err
|
||||||
ident
|
ident
|
||||||
"set! pattern should be nested inside of a list, vector or box")]
|
"set! pattern should be nested inside of a vector, box, or struct")]
|
||||||
[(vector-ref vector index)
|
[(vector-ref vector index)
|
||||||
#`(let ((x #,(subst #'vector)))
|
#`(let ((x #,(subst #'vector)))
|
||||||
(lambda (y) (vector-set! x index y)))]
|
(lambda (y) (vector-set! x index y)))]
|
||||||
|
@ -34,11 +34,19 @@
|
||||||
#`(let ((x #,(subst #'boxed)))
|
#`(let ((x #,(subst #'boxed)))
|
||||||
(lambda (y) (set-box! x y)))]
|
(lambda (y) (set-box! x y)))]
|
||||||
[(car exp)
|
[(car exp)
|
||||||
#`(let ((x #,(subst #'exp)))
|
(match:syntax-err
|
||||||
(lambda (y) (set-car! x y)))]
|
ident
|
||||||
|
"set! cannot be used within list")]
|
||||||
[(cdr exp)
|
[(cdr exp)
|
||||||
|
(match:syntax-err
|
||||||
|
ident
|
||||||
|
"set! cannot be used within list")]
|
||||||
|
[(mcar exp)
|
||||||
#`(let ((x #,(subst #'exp)))
|
#`(let ((x #,(subst #'exp)))
|
||||||
(lambda (y) (set-cdr! x y)))]
|
(lambda (y) (set-mcar! x y)))]
|
||||||
|
[(mcdr exp)
|
||||||
|
#`(let ((x #,(subst #'exp)))
|
||||||
|
(lambda (y) (set-mcdr! x y)))]
|
||||||
[(acc exp)
|
[(acc exp)
|
||||||
(let ([a (assq (syntax-object->datum #'acc) get-c---rs)])
|
(let ([a (assq (syntax-object->datum #'acc) get-c---rs)])
|
||||||
(if a
|
(if a
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
sixth
|
sixth
|
||||||
seventh
|
seventh
|
||||||
eighth
|
eighth
|
||||||
|
last
|
||||||
|
|
||||||
rest
|
rest
|
||||||
|
|
||||||
|
@ -40,6 +41,15 @@
|
||||||
(define-lgetter seventh 7)
|
(define-lgetter seventh 7)
|
||||||
(define-lgetter eighth 8)
|
(define-lgetter eighth 8)
|
||||||
|
|
||||||
|
(define (last x)
|
||||||
|
(unless (and (pair? x)
|
||||||
|
(list? x))
|
||||||
|
(raise-type-error 'rest "non-empty list" x))
|
||||||
|
(let loop ([x x])
|
||||||
|
(if (pair? (cdr x))
|
||||||
|
(loop (cdr x))
|
||||||
|
(car x))))
|
||||||
|
|
||||||
(define (rest x)
|
(define (rest x)
|
||||||
(unless (and (pair? x)
|
(unless (and (pair? x)
|
||||||
(list? x))
|
(list? x))
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
scheme/match
|
scheme/match
|
||||||
scheme/tcp
|
scheme/tcp
|
||||||
scheme/udp
|
scheme/udp
|
||||||
|
scheme/list
|
||||||
(for-syntax scheme/base))
|
(for-syntax scheme/base))
|
||||||
|
|
||||||
(provide (all-from-out scheme/contract
|
(provide (all-from-out scheme/contract
|
||||||
|
@ -19,5 +20,6 @@
|
||||||
scheme/match
|
scheme/match
|
||||||
scheme/base
|
scheme/base
|
||||||
scheme/tcp
|
scheme/tcp
|
||||||
scheme/udp)
|
scheme/udp
|
||||||
|
scheme/list)
|
||||||
(for-syntax (all-from-out scheme/base))))
|
(for-syntax (all-from-out scheme/base))))
|
||||||
|
|
|
@ -1,4 +1,22 @@
|
||||||
|
|
||||||
(module match scheme/base
|
(module match scheme/base
|
||||||
(require mzlib/plt-match)
|
(require mzlib/plt-match
|
||||||
(provide (all-from-out mzlib/plt-match)))
|
(for-syntax scheme/base))
|
||||||
|
(provide (except-out (all-from-out mzlib/plt-match)
|
||||||
|
define-match-expander)
|
||||||
|
(rename-out [define-match-expander* define-match-expander]))
|
||||||
|
|
||||||
|
(define-syntax (no-old-match-form stx)
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"works only for constructor-based `match' form"
|
||||||
|
stx))
|
||||||
|
|
||||||
|
(define-syntax define-match-expander*
|
||||||
|
(syntax-rules ()
|
||||||
|
[(_ id expr) (define-match-expander id expr)]
|
||||||
|
[(_ id expr expr2) (define-match-expander id
|
||||||
|
expr
|
||||||
|
no-old-match-form
|
||||||
|
expr2)])))
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@ Scheme. From @seclink["datatypes"]{Chapter 3} on, this guide dives
|
||||||
into details---covering much of the PLT Scheme toolbox, but leaving
|
into details---covering much of the PLT Scheme toolbox, but leaving
|
||||||
precise details to @|MzScheme| and other reference manuals.
|
precise details to @|MzScheme| and other reference manuals.
|
||||||
|
|
||||||
@bold{This guide describes a potential future version of PLT Scheme.
|
|
||||||
It does not match the current implementation.}
|
|
||||||
|
|
||||||
@table-of-contents[]
|
@table-of-contents[]
|
||||||
|
|
||||||
@include-section["welcome.scrbl"]
|
@include-section["welcome.scrbl"]
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#lang scribble/doc
|
#lang scribble/doc
|
||||||
@require[scribble/manual]
|
@require[scribble/manual
|
||||||
@require[scribble/eval]
|
scribble/eval
|
||||||
@require[scribble/bnf]
|
scribble/bnf
|
||||||
|
scheme/list]
|
||||||
@require["guide-utils.ss"]
|
@require["guide-utils.ss"]
|
||||||
|
|
||||||
@define[step @elem{=}]
|
@define[step @elem{=}]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#lang scribble/doc
|
#lang scribble/doc
|
||||||
@require[scribble/manual]
|
@require[scribble/manual
|
||||||
@require[scribble/eval]
|
scribble/eval]
|
||||||
@require["guide-utils.ss"]
|
@require["guide-utils.ss"]
|
||||||
|
|
||||||
@title[#:tag "intro"]{Welcome to PLT Scheme}
|
@title[#:tag "intro"]{Welcome to PLT Scheme}
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
@title[#:tag-prefix '(lib "quick.scrbl" "scribblings/quick")
|
@title[#:tag-prefix '(lib "quick.scrbl" "scribblings/quick")
|
||||||
#:tag "top"]{An Introduction to PLT Scheme with Pictures}
|
#:tag "top"]{An Introduction to PLT Scheme with Pictures}
|
||||||
|
|
||||||
@bold{This reference describes a potential future version of PLT Scheme.
|
|
||||||
It does not match the current implementation.}
|
|
||||||
|
|
||||||
@; ----------------------------------------------------------------------
|
@; ----------------------------------------------------------------------
|
||||||
|
|
||||||
@require[scribble/manual]
|
@require[scribble/manual]
|
||||||
|
|
|
@ -1,65 +1,101 @@
|
||||||
#lang scheme/base
|
#lang scheme/base
|
||||||
(require scribble/scheme
|
(require scribble/scheme
|
||||||
scribble/basic
|
scribble/basic
|
||||||
scribble/struct)
|
scribble/struct
|
||||||
|
scribble/manual
|
||||||
|
(for-label scheme/base))
|
||||||
|
|
||||||
(provide match-grammar)
|
(provide match-grammar)
|
||||||
|
|
||||||
(define grammar "
|
(define grammar "
|
||||||
pat ::= other-identifier @Match anything, bind identifier
|
pat ::= id @match anything, bind identifier
|
||||||
| _ @Match anything
|
| _ @match anything
|
||||||
| literal @Match literal
|
| literal @match literal
|
||||||
| (QUOTE datum) @Match equal% datum (e.g., symbol)
|
| (QUOTE datum) @match equal% value
|
||||||
| (LIST lvp ...) @Match sequence of lvps
|
| (LIST lvp ...) @match sequence of lvps
|
||||||
| (LIST-REST lvp ... pat) @Match lvps consed onto a pat
|
| (LIST-REST lvp ... pat) @match lvps consed onto a pat
|
||||||
| (LIST-NO-ORDER pat ... lvp) @Match arguments in a list in any order
|
| (LIST-NO-ORDER pat ...) @match pats in any order
|
||||||
| (VECTOR lvp ... lvp) @Match vector of pats
|
| (LIST-NO-ORDER pat ... lvp) @match pats in any order
|
||||||
| (HASH-TABLE (pat pat) ...) @Match hash table mapping pats to pats
|
| (VECTOR lvp ...) @match vector of pats
|
||||||
| (HASH-TABLE (pat pat) ... ooo) @Match hash table mapping pats to pats
|
| (HASH-TABLE (pat pat) ...) @match hash table
|
||||||
| (BOX pat) @Match boxed pat
|
| (HASH-TABLE (pat pat) ...+ ooo) @match hash table
|
||||||
| (STRUCT struct-name (pat ...)) @Match struct-name instance
|
| (BOX pat) @match boxed pat
|
||||||
| (REGEXP rx-expr) @Match astr using (r-match rx-expr ...)
|
| (STRUCT struct-id (pat ...)) @match struct-id instance
|
||||||
| (REGEXP rx-expr pat) @Match astr to rx-expr, pat matches regexp result
|
| (REGEXP rx-expr) @match string
|
||||||
| (PREGEXP prx-expr) @Match astr using (pr-match prx-expr ...)
|
| (REGEXP rx-expr pat) @match string, result with pat
|
||||||
| (PREGEXP prx-expr pat) @Match astr to prx-expr, pat matches pregexp result
|
| (PREGEXP px-expr) @match string
|
||||||
| (AND pat ...) @Match when all pats match
|
| (PREGEXP px-expr pat ) @match string, result with pat
|
||||||
| (OR pat ...) @Match when any pat match
|
| (AND pat ...) @match when all pats match
|
||||||
| (NOT pat ...) @Match when no pat match
|
| (OR pat ...) @match when any pat match
|
||||||
| (APP expr pat) @Match when result of applying expr to the value matches pat
|
| (NOT pat ...) @match when no pat matches
|
||||||
| (? pred-expr pat ...) @Match if pred-expr is true on the value, and all pats match
|
| (APP expr pat) @match (expr value) to pat
|
||||||
| (set! identifier) @Match anything, bind as setter
|
| (? expr pat ...) @match if (expr value) and pats
|
||||||
| (get! identifier) @Match anything, bind as getter
|
| (set! id) @match anything, bind as setter
|
||||||
| (QUASIQUOTE qp) @Match a quasipattern
|
| (get! id) @match anything, bind as getter
|
||||||
literal ::= () @Match the empty list
|
| (QUASIQUOTE qp) @match a quasipattern
|
||||||
| #t @Match true
|
| derived-pattern @match using extension
|
||||||
| #f @Match false
|
literal ::= () @match the empty list
|
||||||
| string @Match equal% string
|
| #t @match true
|
||||||
| number @Match equal% number
|
| #f @match false
|
||||||
| character @Match equal% character
|
| string @match equal% string
|
||||||
lvp ::= (code:line pat ooo) @Greedily match pat instances
|
| number @match equal% number
|
||||||
| pat @Match pat
|
| char @match equal% character
|
||||||
ooo ::= *** @Zero or more (where *** is a keyword)
|
lvp ::= (code:line pat ooo) @greedily match pat instances
|
||||||
| ___ @Zero or more
|
| pat @match pat
|
||||||
| ..K @K or more, where K is a non-negative integer
|
qp ::= literal @match literal
|
||||||
| __K @K or more, where K is a non-negative integer
|
| id @match symbol
|
||||||
qp ::= literal @Match literal
|
| (qp ...) @match sequences of qps
|
||||||
| identifier @Match equal% symbol
|
| (qp ... . qp) @match qps ending qp
|
||||||
| (qp ...) @Match sequences of qps
|
| (qp ... ooo) @match qps ending repeated qp
|
||||||
| (qp ... . qp) @Match sequence of qps consed onto a qp
|
| #(qp ...) @match vector of qps
|
||||||
| (qp ... ooo) @Match qps consed onto a repeated qp
|
| #&qp @match boxed qp
|
||||||
| #(qp ...) @Match vector of qps
|
| ,pat @match pat
|
||||||
| #&qp @Match boxed qp
|
| ,@(LIST lvp ...) @match lvps, spliced
|
||||||
| ,pat @Match pat
|
| ,@(LIST-REST lvp ... pat) @match lvps plus pat, spliced
|
||||||
| ,@(LIST lvp ...) @Match lvp sequence, spliced
|
| ,@'qp @match list-matching qp, spliced
|
||||||
| ,@(LIST-REST lvp ... pat) @Match lvp sequence plus pat, spliced
|
ooo ::= *** @zero or more; *** is literal
|
||||||
| ,@'qp @Match list-matching qp, spliced
|
| ___ @zero or more
|
||||||
|
| ..K @K or more
|
||||||
|
| __K @K or more
|
||||||
")
|
")
|
||||||
|
|
||||||
(define (match-nonterm s)
|
(define (match-nonterm s)
|
||||||
(make-element "schemevariable" (list s)))
|
(make-element "schemevariable" (list s)))
|
||||||
|
|
||||||
|
(define (fixup s middle)
|
||||||
|
(lambda (m)
|
||||||
|
(make-element #f
|
||||||
|
(list (fixup-meaning (substring s 0 (caar m)))
|
||||||
|
middle
|
||||||
|
(fixup-meaning (substring s (cdar m)))))))
|
||||||
|
|
||||||
(define (fixup-meaning s)
|
(define (fixup-meaning s)
|
||||||
s)
|
(cond
|
||||||
|
[(regexp-match-positions #rx"pattern" s)
|
||||||
|
=> (fixup s "pattern")]
|
||||||
|
[(regexp-match-positions #rx"equal%" s)
|
||||||
|
=> (fixup s (scheme equal?))]
|
||||||
|
[(regexp-match-positions #rx"pat" s)
|
||||||
|
=> (fixup s (fixup-sexp 'pat))]
|
||||||
|
[(regexp-match-positions #rx"qp" s)
|
||||||
|
=> (fixup s (fixup-sexp 'qp))]
|
||||||
|
[(regexp-match-positions #rx"lvp" s)
|
||||||
|
=> (fixup s (fixup-sexp 'lvp))]
|
||||||
|
[(regexp-match-positions #rx"struct-id" s)
|
||||||
|
=> (fixup s (fixup-sexp 'struct-id))]
|
||||||
|
[(regexp-match-positions #rx"pred-expr" s)
|
||||||
|
=> (fixup s (fixup-sexp 'pred-expr))]
|
||||||
|
[(regexp-match-positions #rx"expr" s)
|
||||||
|
=> (fixup s (fixup-sexp 'expr))]
|
||||||
|
[(regexp-match-positions #rx"[*][*][*]" s)
|
||||||
|
=> (fixup s (schemeidfont "..."))]
|
||||||
|
[(regexp-match-positions #rx"[(]" s)
|
||||||
|
=> (fixup s (schemeparenfont "("))]
|
||||||
|
[(regexp-match-positions #rx"[)]" s)
|
||||||
|
=> (fixup s (schemeparenfont ")"))]
|
||||||
|
[(regexp-match-positions #rx"K" s)
|
||||||
|
=> (fixup s (match-nonterm "k"))]
|
||||||
|
[else s]))
|
||||||
|
|
||||||
(define (fixup-rhs s)
|
(define (fixup-rhs s)
|
||||||
(let ([r (read (open-input-string s))])
|
(let ([r (read (open-input-string s))])
|
||||||
|
@ -76,10 +112,23 @@ qp ::= literal @Match literal
|
||||||
(box (fixup-sexp (unbox s)))]
|
(box (fixup-sexp (unbox s)))]
|
||||||
[(symbol? s)
|
[(symbol? s)
|
||||||
(case s
|
(case s
|
||||||
[(lvp pat qp literal other-identifier ooo)
|
[(lvp pat qp literal ooo datum struct-id
|
||||||
|
string number character expr id
|
||||||
|
rx-expr px-expr pred-expr
|
||||||
|
derived-pattern)
|
||||||
(match-nonterm (symbol->string s))]
|
(match-nonterm (symbol->string s))]
|
||||||
[(QUOTE LIST)
|
[(QUOTE LIST LIST-REST LIST-NO-ORDER VECTOR HASH-TABLE BOX STRUCT
|
||||||
|
REGEXP PREGEXP AND OR NOT APP ? get! set! QUASIQUOTE)
|
||||||
(make-element "schemesymbol" (list (string-downcase (symbol->string s))))]
|
(make-element "schemesymbol" (list (string-downcase (symbol->string s))))]
|
||||||
|
[(***)
|
||||||
|
(make-element "schemesymbol" '("..."))]
|
||||||
|
[(___) (make-element "schemesymbol" '("___"))]
|
||||||
|
[(__K)
|
||||||
|
(make-element #f (list (make-element "schemesymbol" '("__"))
|
||||||
|
(match-nonterm "k")))]
|
||||||
|
[(..K)
|
||||||
|
(make-element #f (list (make-element "schemesymbol" '(".."))
|
||||||
|
(match-nonterm "k")))]
|
||||||
[else
|
[else
|
||||||
s])]
|
s])]
|
||||||
[else s]))
|
[else s]))
|
||||||
|
|
|
@ -1,10 +1,411 @@
|
||||||
#lang scribble/doc
|
#lang scribble/doc
|
||||||
@require["mz.ss"
|
@require["mz.ss"
|
||||||
"match-grammar.ss"]
|
"match-grammar.ss"
|
||||||
|
scheme/match]
|
||||||
|
|
||||||
@title[#:tag "match"]{Pattern Matching}
|
@title[#:tag "match"]{Pattern Matching}
|
||||||
|
|
||||||
|
The @scheme[match] form and related forms support general pattern
|
||||||
|
matching on Scheme values. See also @secref["regexp"] for information
|
||||||
|
on regular-expression matching on strings, bytes, and streams.
|
||||||
|
|
||||||
|
@defform/subs[(match val-expr clause ...)
|
||||||
|
([clause [pat expr ...+]
|
||||||
|
[pat (=> identifier) expr ...+]])]{
|
||||||
|
|
||||||
|
Finds the first @scheme[pat] that matches the result of
|
||||||
|
@scheme[val-expr], and evaluates the corresponding @scheme[expr]s with
|
||||||
|
bindings introduced by @scheme[pat] (if any). The last @scheme[expr]
|
||||||
|
in the matching clause is evaluated in tail position with respect to
|
||||||
|
the @scheme[match] expression.
|
||||||
|
|
||||||
|
An optional @scheme[(=> identifier)] between a @scheme[pat] and the
|
||||||
|
@scheme[expr]s is bound to a @defterm{failure procedure} of zero
|
||||||
|
arguments. If this procedure is invoked, it escapes back to the
|
||||||
|
pattern matching expression, and resumes the matching process as if
|
||||||
|
the pattern had failed to match. The @scheme[expr]s must not mutate
|
||||||
|
the object being matched before calling the failure procedure,
|
||||||
|
otherwise the behavior of matching is unpredictable.
|
||||||
|
|
||||||
|
The grammar of @scheme[pat] is as follows, where non-italicized
|
||||||
|
identifers are recognized symbolically (i.e., not by binding).
|
||||||
|
|
||||||
@|match-grammar|
|
@|match-grammar|
|
||||||
|
|
||||||
@defform[(match expr [pat expr ...+] ...)]{
|
In more detail, patterns match as follows:
|
||||||
|
|
||||||
|
@itemize{
|
||||||
|
|
||||||
|
@item{@scheme[_id], excluding the reserved names @schemeidfont{"_"},
|
||||||
|
@schemeidfont{"..."}, @schemeidfont{".._"},
|
||||||
|
@schemeidfont{".."}@scheme[_k], and
|
||||||
|
@schemeidfont{".."}@scheme[_k] for non-negative integers
|
||||||
|
@scheme[_k] --- matches anything, and binds @scheme[id] to the
|
||||||
|
matching values. If an @scheme[_id] is used multiple times
|
||||||
|
within a pattern, the corresponding matches must be the same
|
||||||
|
according to @scheme[(match-equality-test)], except that
|
||||||
|
instances of an @scheme[_id] in different @schemeidfont{or} and
|
||||||
|
@schemeidfont{not} sub-patterns are independent.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2 3)
|
||||||
|
[(list a b a) (list a b)]
|
||||||
|
[(list a b c) (list c b a)])
|
||||||
|
(match '(1 '(x y z) 1)
|
||||||
|
[(list a b a) (list a b)]
|
||||||
|
[(list a b c) (list c b a)])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@schemeidfont{_} --- matches anything, without binding any
|
||||||
|
identifiers.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2 3)
|
||||||
|
[(list _ _ a) a])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[#t], @scheme[#f], @scheme[_string], @scheme[_number],
|
||||||
|
@scheme[_char], or @scheme[(#,(schemeidfont "quote") _datum)]
|
||||||
|
--- matches an @scheme[equal?] constant.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match "yes"
|
||||||
|
["no" #f]
|
||||||
|
["yes" #t])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "list") _lvp ...)] --- matches a list
|
||||||
|
of elements. In the case of @scheme[(#,(schemeidfont "list")
|
||||||
|
_pat ...)], the pattern matches a list with as many element as
|
||||||
|
@scheme[_pat]s, and each element must match the corresponding
|
||||||
|
@scheme[_pat]. In the more general case, each @scheme[_lvp]
|
||||||
|
corresponds to a ``spliced'' list of greedy matches.
|
||||||
|
|
||||||
|
For spliced lists, @schemeidfont{...} and @schemeidfont{___}
|
||||||
|
are synonyms for zero or more matches. The
|
||||||
|
@schemeidfont{..}@scheme[_k] and @schemeidfont{__}@scheme[_k]
|
||||||
|
forms are also synonyms, specifying @scheme[_k] or more
|
||||||
|
matches. Pattern variables that precede these splicing
|
||||||
|
operators are bound to lists of matching forms.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2 3)
|
||||||
|
[(list a b c) (list c b a)])
|
||||||
|
(match '(1 2 3)
|
||||||
|
[(list 1 a ...) a])
|
||||||
|
(match '(1 2 3)
|
||||||
|
[(list 1 a ..3) a]
|
||||||
|
[_ 'else])
|
||||||
|
(match '(1 2 3 4)
|
||||||
|
[(list 1 a ..3) a]
|
||||||
|
[_ 'else])
|
||||||
|
(match '(1 2 3 4 5)
|
||||||
|
[(list 1 a ..3 5) a] (code:comment #, @t{greedy matching to @scheme[a] leaves no @scheme[5]})
|
||||||
|
[_ 'else])
|
||||||
|
(match '(1 (2) (2) (2) 5)
|
||||||
|
[(list 1 (list a) ..3 5) a]
|
||||||
|
[_ 'else])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "list-rest") _lvp ... _pat)] ---
|
||||||
|
similar to a @schemeidfont{list} pattern, but the final
|
||||||
|
@scheme[_pat] matches the ``rest'' of the list after the last
|
||||||
|
@scheme[_lvp]. In fact, the matched value can be a non-list
|
||||||
|
chain of pairs (i.e., an ``improper list'') if @scheme[_pat]
|
||||||
|
matches non-list values.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2 3 . 4)
|
||||||
|
[(list-rest a b c d) d])
|
||||||
|
(match '(1 2 3 . 4)
|
||||||
|
[(list-rest a ... d) (list a d)])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "list-no-order") _pat ...)] ---
|
||||||
|
similar to a @schemeidfont{list} pattern, but the elements to
|
||||||
|
match each @scheme[_pat] can appear in the list in any order.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2 3)
|
||||||
|
[(list-no-order 3 2 x) x])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "list-no-order") _pat ... _lvp)] ---
|
||||||
|
generalizes @schemeidfont{list-no-order} to allow a pattern
|
||||||
|
that matches multiple list elements that are interspersed in
|
||||||
|
any order with matches for the other patterns.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2 3 4 5 6)
|
||||||
|
[(list-no-order 6 2 y ...) y])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "vector") _lvp ...)] --- like a
|
||||||
|
@schemeidfont{list} pattern, but matching a vector.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match #(1 (2) (2) (2) 5)
|
||||||
|
[(vector 1 (list a) ..3 5) a])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "hash-table") (_pat _pat) ...)] ---
|
||||||
|
similar to @schemeidfont{list-no-order}, but matching against
|
||||||
|
hash table's key--value pairs.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match #hash(("a" . 1) ("b" . 2))
|
||||||
|
[(hash-table ("b" b) ("a" a)) (list b a)])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "hash-table") (_pat _pat) ...+ _ooo)]
|
||||||
|
--- Generalizes @schemeidfont{hash-table} to support a final
|
||||||
|
repeating pattern.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match #hash(("a" . 1) ("b" . 2))
|
||||||
|
[(hash-table (key val) ...) key])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "box") _pat)] --- matches a boxed value.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match #&1
|
||||||
|
[(box a) a])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "struct") _struct-id (_pat ...))] ---
|
||||||
|
matches an instance of a structure type names
|
||||||
|
@scheme[_struct-id], where each field int he instance matches
|
||||||
|
the corresponding @scheme[_pat].
|
||||||
|
|
||||||
|
Usually, @scheme[struct-id] is defined with
|
||||||
|
@scheme[define-struct]. More generally, @scheme[struct-id]
|
||||||
|
must be bound to expansion-time information for a structure
|
||||||
|
type (see @secref["structinfo"]), where the information
|
||||||
|
includes at least a predicate binding and field accessor
|
||||||
|
bindings corresponding to the number of field
|
||||||
|
@scheme[_pat]s. In particular, a module import or a
|
||||||
|
@scheme[unit] import with a signature containing a
|
||||||
|
@scheme[struct] declaration can provide the structure type
|
||||||
|
information.
|
||||||
|
|
||||||
|
@defexamples[
|
||||||
|
(define-struct tree (val left right))
|
||||||
|
(match (make-tree 0 (make-tree 1 #f #f) #f)
|
||||||
|
[(struct tree (a (struct tree (b _ _)) _)) (list a b)])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "regexp") _rx-expr)] --- matches a
|
||||||
|
string that matches the regexp pattern produced by
|
||||||
|
@scheme[_rx-expr]; see @secref["regexp"] for more information
|
||||||
|
about regexps.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match "apple"
|
||||||
|
[(regexp #rx"p+") 'yes]
|
||||||
|
[_ 'no])
|
||||||
|
(match "banana"
|
||||||
|
[(regexp #rx"p+") 'yes]
|
||||||
|
[_ 'no])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "regexp") _rx-expr _pat)] --- extends
|
||||||
|
the @schemeidfont{regexp} form to further constrain the match
|
||||||
|
where the result of @scheme[regexp-match] is matched against
|
||||||
|
@scheme[_pat].
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match "apple"
|
||||||
|
[(regexp #rx"p+(.)" (list _ "l")) 'yes]
|
||||||
|
[_ 'no])
|
||||||
|
(match "append"
|
||||||
|
[(regexp #rx"p+(.)" (list _ "l")) 'yes]
|
||||||
|
[_ 'no])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "pregexp") _rx-expr)] or
|
||||||
|
@scheme[(#,(schemeidfont "regexp") _rx-expr _pat)] --- like the
|
||||||
|
@schemeidfont{regexp} patterns, but if @scheme[_rx-expr]
|
||||||
|
produces a string, it is converted to a pattern using
|
||||||
|
@scheme[pregexp] instead of @scheme[regexp].}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "and") _pat ...)] --- matches if all
|
||||||
|
of the @scheme[_pat]s match. This pattern is often used as
|
||||||
|
@scheme[(#,(schemeidfont "and") _id _pat)] to bind @scheme[_id]
|
||||||
|
to the entire value that matches @scheme[pat].
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 (2 3) 4)
|
||||||
|
[(list _ (and a (list _ ...)) _) a])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "or") _pat ...)] --- matches if any of
|
||||||
|
the @scheme[_pat]s match. @bold{Beware}: the result expression
|
||||||
|
can be duplicated once for each @scheme[_pat]! Identifiers in
|
||||||
|
@scheme[_pat] are bound only in the corresponding copy of the
|
||||||
|
result expression; in a module context, if the result
|
||||||
|
expression refers to a binding, then that all @scheme[_pat]s
|
||||||
|
must include the binding.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2)
|
||||||
|
[(or (list a 1) (list a 2)) a])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "not") _pat ...)] --- matches when
|
||||||
|
none of the @scheme[_pat]s match, and binds no identifiers.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2 3)
|
||||||
|
[(list (not 4) ...) 'yes]
|
||||||
|
[_ 'no])
|
||||||
|
(match '(1 4 3)
|
||||||
|
[(list (not 4) ...) 'yes]
|
||||||
|
[_ 'no])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "app") _expr _pat)] --- applies
|
||||||
|
@scheme[_expr] to the value to be matched; the result of the
|
||||||
|
application is matched again @scheme[_pat].
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2)
|
||||||
|
[(app length 2) 'yes])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "?") _expr _pat ...)] --- applies
|
||||||
|
@scheme[_expr] to the value to be matched, and checks whether
|
||||||
|
the result is a true value; the additional @scheme[_pat]s must
|
||||||
|
also match (i.e., @schemeidfont{?} combines a predicate
|
||||||
|
application and an @schemeidfont{and} pattern).
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 3 5)
|
||||||
|
[(list (? odd?) ...) 'yes])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "set!") _id)] --- matches anything,
|
||||||
|
and binds @scheme[_id] to a procedure that takes one argument
|
||||||
|
and mutates the matched value to install the given one in the
|
||||||
|
matched position. This form can be used only within a
|
||||||
|
@schemeidfont{vector}, @schemeidfont{box}, or
|
||||||
|
@schemeidfont{struct} pattern.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(define v (vector 1 2 3))
|
||||||
|
(match v
|
||||||
|
[(vector _ (set! s!) _) (s! 0)])
|
||||||
|
v
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "get!") _id)] --- matches anything, and
|
||||||
|
binds @scheme[_id] to a thunk that extracts the matched
|
||||||
|
position from the matched value, which is useful when the
|
||||||
|
matched position is mutable. This form can be used
|
||||||
|
only in the same places as the @schemeidfont{set!} pattern.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(define v (vector 1 2 3))
|
||||||
|
(define g
|
||||||
|
(match v
|
||||||
|
[(vector _ (get! g) _) g]))
|
||||||
|
(vector-set! v 1 0)
|
||||||
|
(g)
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[(#,(schemeidfont "quasiquote") _qp)] --- introduces a
|
||||||
|
quasipattern, in which identifiers match symbols. Like the
|
||||||
|
@scheme[quasiquote] expression form, @schemeidfont{unquote}
|
||||||
|
and @schemeidfont{unquote-splicing} escape back to normal
|
||||||
|
patterns.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match '(1 2 3)
|
||||||
|
[`(1 ,a ,(? odd? b)) (list a b)])
|
||||||
|
]}
|
||||||
|
|
||||||
|
@item{@scheme[_derived-pattern] --- matches a pattern defined by a
|
||||||
|
macro extension via @scheme[define-match-expander].}
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
@; ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@section{Combined Matching Forms}
|
||||||
|
|
||||||
|
@defform[(match-lambda clause ...)]{
|
||||||
|
|
||||||
|
Equivalent to @scheme[(lambda (id) (match id clause ...))].
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@defform[(match-lambda* clause ...)]{
|
||||||
|
|
||||||
|
Equivalent to @scheme[(lambda lst (match lst clause ...))].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defform[(match-let ([pat expr] ...) body ...+)]{
|
||||||
|
|
||||||
|
Generalizes @scheme[let] to support pattern bindings. Each
|
||||||
|
@scheme[expr] is matched against its corresponding @scheme[pat] (the
|
||||||
|
match must succeed), and the bindings that @scheme[pat] introduces are
|
||||||
|
visible in the @scheme[body]s.
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match-let ([(list a b) '(1 2)]
|
||||||
|
[(vector x ...) #(1 2 3 4)])
|
||||||
|
(list b a x))
|
||||||
|
]}
|
||||||
|
|
||||||
|
@defform[(match-let* ([pat expr] ...) body ...+)]{
|
||||||
|
|
||||||
|
Like @scheme[match-let], but generalizes @scheme[let*], so that the
|
||||||
|
bindings of each @scheme[pat] are available in each subsequent
|
||||||
|
@scheme[expr].
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match-let* ([(list a b) '(#(1 2 3 4) 2)]
|
||||||
|
[(vector x ...) a])
|
||||||
|
x)
|
||||||
|
]}
|
||||||
|
|
||||||
|
@defform[(match-letrec ([pat expr] ...) body ...+)]{
|
||||||
|
|
||||||
|
Like @scheme[match-let], but generalizes @scheme[letrec].}
|
||||||
|
|
||||||
|
|
||||||
|
@defform[(match-define pat expr)]{
|
||||||
|
|
||||||
|
Defines the names bound by @scheme[pat] to the values produced by
|
||||||
|
matching against the result of @scheme[expr].
|
||||||
|
|
||||||
|
@examples[
|
||||||
|
(match-define (list a b) '(1 2))
|
||||||
|
b
|
||||||
|
]}
|
||||||
|
|
||||||
|
@; ----------------------------------------
|
||||||
|
|
||||||
|
@section{Extending @scheme[match]}
|
||||||
|
|
||||||
|
@defform*[((define-match-expander id proc-expr)
|
||||||
|
(define-match-expander id proc-expr proc-expr))]{
|
||||||
|
|
||||||
|
Binds @scheme[id] to a pattern transformer.
|
||||||
|
|
||||||
|
The first @scheme[proc-expr] subexpression must evaluate to a
|
||||||
|
transformer that produces a @scheme[_pat] for @scheme[match].
|
||||||
|
Whenever @scheme[id] appears as the beginning of a pattern, this
|
||||||
|
transformer is given, at expansion time, a syntax object
|
||||||
|
corresponding to the entire pattern (including @scheme[id]). The
|
||||||
|
pattern is the replaced with the result of the transformer.
|
||||||
|
|
||||||
|
A transformer produced by a second @scheme[proc-expr] subexpression is
|
||||||
|
used when @scheme[id] is used in an expression context. Using the
|
||||||
|
second @scheme[proc-expr], @scheme[id] can be given meaning both
|
||||||
|
inside and outside patterns.}
|
||||||
|
|
||||||
|
@defparam[match-equality-test comp-proc (any/c any/c . -> . any)]{
|
||||||
|
|
||||||
|
A parameter that determines the comparison procedure used to check
|
||||||
|
whether multiple uses of an identifier match the ``same'' value. The
|
||||||
|
default is @scheme[equal?].}
|
||||||
|
|
|
@ -18,6 +18,15 @@
|
||||||
(define AllUnix "Unix and Mac OS X")
|
(define AllUnix "Unix and Mac OS X")
|
||||||
(provide AllUnix)
|
(provide AllUnix)
|
||||||
|
|
||||||
|
(provide note-lib)
|
||||||
|
(define-syntax-rule (note-lib lib)
|
||||||
|
(t "The bindings documented in this section are provided by the "
|
||||||
|
(schemeidfont "scheme/list")
|
||||||
|
" and "
|
||||||
|
(schemeidfont "scheme")
|
||||||
|
" libraries, but not " (schemeidfont "scheme/base")
|
||||||
|
"."))
|
||||||
|
|
||||||
(define (*exnraise s)
|
(define (*exnraise s)
|
||||||
(make-element #f (list s " exception is raised")))
|
(make-element #f (list s " exception is raised")))
|
||||||
(define-syntax exnraise
|
(define-syntax exnraise
|
||||||
|
|
|
@ -53,13 +53,9 @@ of the sequence. See also @scheme[in-list].
|
||||||
@defproc[(pair? [v any/c]) boolean?]{Returns @scheme[#t] if @scheme[v] is
|
@defproc[(pair? [v any/c]) boolean?]{Returns @scheme[#t] if @scheme[v] is
|
||||||
a pair, @scheme[#f] otherwise.}
|
a pair, @scheme[#f] otherwise.}
|
||||||
|
|
||||||
@defproc[(cons? [v any/c]) boolean?]{The same as @scheme[(pair? v)].}
|
|
||||||
|
|
||||||
@defproc[(null? [v any/c]) boolean?]{Returns @scheme[#t] if @scheme[v] is
|
@defproc[(null? [v any/c]) boolean?]{Returns @scheme[#t] if @scheme[v] is
|
||||||
the empty list, @scheme[#f] otherwise.}
|
the empty list, @scheme[#f] otherwise.}
|
||||||
|
|
||||||
@defproc[(empty? [v any/c]) boolean?]{The same as @scheme[(null? v)].}
|
|
||||||
|
|
||||||
@defproc[(cons [a any/c] [d any/c]) pair?]{Returns a pair whose first
|
@defproc[(cons [a any/c] [d any/c]) pair?]{Returns a pair whose first
|
||||||
element is @scheme[a] and second element is @scheme[d].}
|
element is @scheme[a] and second element is @scheme[d].}
|
||||||
|
|
||||||
|
@ -69,14 +65,8 @@ pair @scheme[p].}
|
||||||
@defproc[(cdr [p pair?]) any/c]{Returns the second element of the
|
@defproc[(cdr [p pair?]) any/c]{Returns the second element of the
|
||||||
pair @scheme[p].}
|
pair @scheme[p].}
|
||||||
|
|
||||||
@defproc[(first [p pair?]) any/c]{The same as @scheme[(car p)].}
|
|
||||||
|
|
||||||
@defproc[(rest [p pair?]) any/c]{The same as @scheme[(cdr p)].}
|
|
||||||
|
|
||||||
@defthing[null null?]{The empty list.}
|
@defthing[null null?]{The empty list.}
|
||||||
|
|
||||||
@defthing[empty null?]{The empty list.}
|
|
||||||
|
|
||||||
|
|
||||||
@defproc[(list? [v any/c]) boolean?]{Returns @scheme[#t] if @scheme[v]
|
@defproc[(list? [v any/c]) boolean?]{Returns @scheme[#t] if @scheme[v]
|
||||||
is a list: either the empty list, or a pair whose second element is a
|
is a list: either the empty list, or a pair whose second element is a
|
||||||
|
@ -458,3 +448,35 @@ Like @scheme[assoc], but finds an element using the predicate
|
||||||
@defc_r[d d d a]
|
@defc_r[d d d a]
|
||||||
@defc_r[d d d d]
|
@defc_r[d d d d]
|
||||||
|
|
||||||
|
@; ----------------------------------------
|
||||||
|
@section{List Synonyms}
|
||||||
|
|
||||||
|
@declare-exporting[scheme/list scheme]
|
||||||
|
|
||||||
|
@note-lib[scheme/list]
|
||||||
|
|
||||||
|
@defthing[empty null?]{The empty list.}
|
||||||
|
|
||||||
|
@defproc[(cons? [v any/c]) boolean?]{The same as @scheme[(pair? v)].}
|
||||||
|
|
||||||
|
@defproc[(empty? [v any/c]) boolean?]{The same as @scheme[(null? v)].}
|
||||||
|
|
||||||
|
@defproc[(first [lst list?]) any/c]{The same as @scheme[(car lst)], but only for no-empty lists.}
|
||||||
|
|
||||||
|
@defproc[(rest [lst list?]) list?]{The same as @scheme[(cdr lst)], but only for non-empty lists.}
|
||||||
|
|
||||||
|
@defproc[(second [lst list?]) any]{Returns the second element of the list.}
|
||||||
|
|
||||||
|
@defproc[(third [lst list?]) any]{Returns the third element of the list.}
|
||||||
|
|
||||||
|
@defproc[(fourth [lst list?]) any]{Returns the fourth element of the list.}
|
||||||
|
|
||||||
|
@defproc[(fifth [lst list?]) any]{Returns the fifth element of the list.}
|
||||||
|
|
||||||
|
@defproc[(sixth [lst list?]) any]{Returns the sixth element of the list.}
|
||||||
|
|
||||||
|
@defproc[(seventh [lst list?]) any]{Returns the seventh element of the list.}
|
||||||
|
|
||||||
|
@defproc[(eighth [lst list?]) any]{Returns the eighth element of the list.}
|
||||||
|
|
||||||
|
@defproc[(last [lst list?]) any]{Returns the last element of the list.}
|
||||||
|
|
|
@ -11,9 +11,6 @@ most prominent libraries. The companion manual @|Guide| provides a
|
||||||
friendlier (though less precise and less complete) overview of the
|
friendlier (though less precise and less complete) overview of the
|
||||||
language.
|
language.
|
||||||
|
|
||||||
@bold{This reference describes a potential future version of PLT Scheme.
|
|
||||||
It does not match the current implementation.}
|
|
||||||
|
|
||||||
@table-of-contents[]
|
@table-of-contents[]
|
||||||
|
|
||||||
@include-section["model.scrbl"]
|
@include-section["model.scrbl"]
|
||||||
|
|
|
@ -5,12 +5,6 @@
|
||||||
(define list-mutable/c #t)
|
(define list-mutable/c #t)
|
||||||
(define cons-mutable/c #t)
|
(define cons-mutable/c #t)
|
||||||
|
|
||||||
(define cons? #f)
|
|
||||||
(define first #f)
|
|
||||||
(define rest #f)
|
|
||||||
(define empty? #f)
|
|
||||||
(define empty #f)
|
|
||||||
|
|
||||||
(define arity? #f)
|
(define arity? #f)
|
||||||
|
|
||||||
(provide (all-defined)))
|
(provide (all-defined)))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user