match docs
svn: r7817
This commit is contained in:
parent
27f7f770b8
commit
44478fa8e0
|
@ -12,21 +12,21 @@
|
|||
;;!(function setter
|
||||
;; (form (setter e ident let-bound) -> 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
|
||||
;; represents a function that is able to set the value that the
|
||||
;; expression points to.
|
||||
(define (setter e ident let-bound)
|
||||
(define (subst e) (subst-bindings e let-bound))
|
||||
(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
|
||||
(not (stx-pair? #'p))
|
||||
(match:syntax-err
|
||||
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)
|
||||
#`(let ((x #,(subst #'vector)))
|
||||
(lambda (y) (vector-set! x index y)))]
|
||||
|
@ -34,11 +34,19 @@
|
|||
#`(let ((x #,(subst #'boxed)))
|
||||
(lambda (y) (set-box! x y)))]
|
||||
[(car exp)
|
||||
#`(let ((x #,(subst #'exp)))
|
||||
(lambda (y) (set-car! x y)))]
|
||||
(match:syntax-err
|
||||
ident
|
||||
"set! cannot be used within list")]
|
||||
[(cdr exp)
|
||||
(match:syntax-err
|
||||
ident
|
||||
"set! cannot be used within list")]
|
||||
[(mcar 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)
|
||||
(let ([a (assq (syntax-object->datum #'acc) get-c---rs)])
|
||||
(if a
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
sixth
|
||||
seventh
|
||||
eighth
|
||||
last
|
||||
|
||||
rest
|
||||
|
||||
|
@ -40,6 +41,15 @@
|
|||
(define-lgetter seventh 7)
|
||||
(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)
|
||||
(unless (and (pair? x)
|
||||
(list? x))
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
scheme/match
|
||||
scheme/tcp
|
||||
scheme/udp
|
||||
scheme/list
|
||||
(for-syntax scheme/base))
|
||||
|
||||
(provide (all-from-out scheme/contract
|
||||
|
@ -19,5 +20,6 @@
|
|||
scheme/match
|
||||
scheme/base
|
||||
scheme/tcp
|
||||
scheme/udp)
|
||||
scheme/udp
|
||||
scheme/list)
|
||||
(for-syntax (all-from-out scheme/base))))
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
|
||||
(module match scheme/base
|
||||
(require mzlib/plt-match)
|
||||
(provide (all-from-out mzlib/plt-match)))
|
||||
(require 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
|
||||
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[]
|
||||
|
||||
@include-section["welcome.scrbl"]
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#lang scribble/doc
|
||||
@require[scribble/manual]
|
||||
@require[scribble/eval]
|
||||
@require[scribble/bnf]
|
||||
@require[scribble/manual
|
||||
scribble/eval
|
||||
scribble/bnf
|
||||
scheme/list]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@define[step @elem{=}]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#lang scribble/doc
|
||||
@require[scribble/manual]
|
||||
@require[scribble/eval]
|
||||
@require[scribble/manual
|
||||
scribble/eval]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@title[#:tag "intro"]{Welcome to PLT Scheme}
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
@title[#:tag-prefix '(lib "quick.scrbl" "scribblings/quick")
|
||||
#: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]
|
||||
|
|
|
@ -1,65 +1,101 @@
|
|||
#lang scheme/base
|
||||
(require scribble/scheme
|
||||
scribble/basic
|
||||
scribble/struct)
|
||||
scribble/struct
|
||||
scribble/manual
|
||||
(for-label scheme/base))
|
||||
|
||||
(provide match-grammar)
|
||||
|
||||
(define grammar "
|
||||
pat ::= other-identifier @Match anything, bind identifier
|
||||
| _ @Match anything
|
||||
| literal @Match literal
|
||||
| (QUOTE datum) @Match equal% datum (e.g., symbol)
|
||||
| (LIST lvp ...) @Match sequence of lvps
|
||||
| (LIST-REST lvp ... pat) @Match lvps consed onto a pat
|
||||
| (LIST-NO-ORDER pat ... lvp) @Match arguments in a list in any order
|
||||
| (VECTOR lvp ... lvp) @Match vector of pats
|
||||
| (HASH-TABLE (pat pat) ...) @Match hash table mapping pats to pats
|
||||
| (HASH-TABLE (pat pat) ... ooo) @Match hash table mapping pats to pats
|
||||
| (BOX pat) @Match boxed pat
|
||||
| (STRUCT struct-name (pat ...)) @Match struct-name instance
|
||||
| (REGEXP rx-expr) @Match astr using (r-match rx-expr ...)
|
||||
| (REGEXP rx-expr pat) @Match astr to rx-expr, pat matches regexp result
|
||||
| (PREGEXP prx-expr) @Match astr using (pr-match prx-expr ...)
|
||||
| (PREGEXP prx-expr pat) @Match astr to prx-expr, pat matches pregexp result
|
||||
| (AND pat ...) @Match when all pats match
|
||||
| (OR pat ...) @Match when any pat match
|
||||
| (NOT pat ...) @Match when no pat match
|
||||
| (APP expr pat) @Match when result of applying expr to the value matches pat
|
||||
| (? pred-expr pat ...) @Match if pred-expr is true on the value, and all pats match
|
||||
| (set! identifier) @Match anything, bind as setter
|
||||
| (get! identifier) @Match anything, bind as getter
|
||||
| (QUASIQUOTE qp) @Match a quasipattern
|
||||
literal ::= () @Match the empty list
|
||||
| #t @Match true
|
||||
| #f @Match false
|
||||
| string @Match equal% string
|
||||
| number @Match equal% number
|
||||
| character @Match equal% character
|
||||
lvp ::= (code:line pat ooo) @Greedily match pat instances
|
||||
| pat @Match pat
|
||||
ooo ::= *** @Zero or more (where *** is a keyword)
|
||||
| ___ @Zero or more
|
||||
| ..K @K or more, where K is a non-negative integer
|
||||
| __K @K or more, where K is a non-negative integer
|
||||
qp ::= literal @Match literal
|
||||
| identifier @Match equal% symbol
|
||||
| (qp ...) @Match sequences of qps
|
||||
| (qp ... . qp) @Match sequence of qps consed onto a qp
|
||||
| (qp ... ooo) @Match qps consed onto a repeated qp
|
||||
| #(qp ...) @Match vector of qps
|
||||
| #&qp @Match boxed qp
|
||||
| ,pat @Match pat
|
||||
| ,@(LIST lvp ...) @Match lvp sequence, spliced
|
||||
| ,@(LIST-REST lvp ... pat) @Match lvp sequence plus pat, spliced
|
||||
| ,@'qp @Match list-matching qp, spliced
|
||||
pat ::= id @match anything, bind identifier
|
||||
| _ @match anything
|
||||
| literal @match literal
|
||||
| (QUOTE datum) @match equal% value
|
||||
| (LIST lvp ...) @match sequence of lvps
|
||||
| (LIST-REST lvp ... pat) @match lvps consed onto a pat
|
||||
| (LIST-NO-ORDER pat ...) @match pats in any order
|
||||
| (LIST-NO-ORDER pat ... lvp) @match pats in any order
|
||||
| (VECTOR lvp ...) @match vector of pats
|
||||
| (HASH-TABLE (pat pat) ...) @match hash table
|
||||
| (HASH-TABLE (pat pat) ...+ ooo) @match hash table
|
||||
| (BOX pat) @match boxed pat
|
||||
| (STRUCT struct-id (pat ...)) @match struct-id instance
|
||||
| (REGEXP rx-expr) @match string
|
||||
| (REGEXP rx-expr pat) @match string, result with pat
|
||||
| (PREGEXP px-expr) @match string
|
||||
| (PREGEXP px-expr pat ) @match string, result with pat
|
||||
| (AND pat ...) @match when all pats match
|
||||
| (OR pat ...) @match when any pat match
|
||||
| (NOT pat ...) @match when no pat matches
|
||||
| (APP expr pat) @match (expr value) to pat
|
||||
| (? expr pat ...) @match if (expr value) and pats
|
||||
| (set! id) @match anything, bind as setter
|
||||
| (get! id) @match anything, bind as getter
|
||||
| (QUASIQUOTE qp) @match a quasipattern
|
||||
| derived-pattern @match using extension
|
||||
literal ::= () @match the empty list
|
||||
| #t @match true
|
||||
| #f @match false
|
||||
| string @match equal% string
|
||||
| number @match equal% number
|
||||
| char @match equal% character
|
||||
lvp ::= (code:line pat ooo) @greedily match pat instances
|
||||
| pat @match pat
|
||||
qp ::= literal @match literal
|
||||
| id @match symbol
|
||||
| (qp ...) @match sequences of qps
|
||||
| (qp ... . qp) @match qps ending qp
|
||||
| (qp ... ooo) @match qps ending repeated qp
|
||||
| #(qp ...) @match vector of qps
|
||||
| #&qp @match boxed qp
|
||||
| ,pat @match pat
|
||||
| ,@(LIST lvp ...) @match lvps, spliced
|
||||
| ,@(LIST-REST lvp ... pat) @match lvps plus pat, spliced
|
||||
| ,@'qp @match list-matching qp, spliced
|
||||
ooo ::= *** @zero or more; *** is literal
|
||||
| ___ @zero or more
|
||||
| ..K @K or more
|
||||
| __K @K or more
|
||||
")
|
||||
|
||||
(define (match-nonterm 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)
|
||||
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)
|
||||
(let ([r (read (open-input-string s))])
|
||||
|
@ -76,10 +112,23 @@ qp ::= literal @Match literal
|
|||
(box (fixup-sexp (unbox s)))]
|
||||
[(symbol? 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))]
|
||||
[(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" '("..."))]
|
||||
[(___) (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
|
||||
s])]
|
||||
[else s]))
|
||||
|
|
|
@ -1,10 +1,411 @@
|
|||
#lang scribble/doc
|
||||
@require["mz.ss"
|
||||
"match-grammar.ss"]
|
||||
"match-grammar.ss"
|
||||
scheme/match]
|
||||
|
||||
@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|
|
||||
|
||||
@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")
|
||||
(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)
|
||||
(make-element #f (list s " exception is raised")))
|
||||
(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
|
||||
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
|
||||
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
|
||||
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
|
||||
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[empty null?]{The empty list.}
|
||||
|
||||
|
||||
@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
|
||||
|
@ -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 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
|
||||
language.
|
||||
|
||||
@bold{This reference describes a potential future version of PLT Scheme.
|
||||
It does not match the current implementation.}
|
||||
|
||||
@table-of-contents[]
|
||||
|
||||
@include-section["model.scrbl"]
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
(define list-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)
|
||||
|
||||
(provide (all-defined)))
|
||||
|
|
Loading…
Reference in New Issue
Block a user