diff --git a/collects/mzlib/private/match/getter-setter.scm b/collects/mzlib/private/match/getter-setter.scm index 5868af55a1..dd884143dd 100644 --- a/collects/mzlib/private/match/getter-setter.scm +++ b/collects/mzlib/private/match/getter-setter.scm @@ -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 diff --git a/collects/scheme/list.ss b/collects/scheme/list.ss index 631ea7094e..d5024c794c 100644 --- a/collects/scheme/list.ss +++ b/collects/scheme/list.ss @@ -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)) diff --git a/collects/scheme/main.ss b/collects/scheme/main.ss index 846d6e01c3..80174c9797 100644 --- a/collects/scheme/main.ss +++ b/collects/scheme/main.ss @@ -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)))) diff --git a/collects/scheme/match.ss b/collects/scheme/match.ss index 9085fdf5a8..e511d3454b 100644 --- a/collects/scheme/match.ss +++ b/collects/scheme/match.ss @@ -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)]))) + diff --git a/collects/scribblings/guide/guide.scrbl b/collects/scribblings/guide/guide.scrbl index b33066c3dc..e714f39acd 100644 --- a/collects/scribblings/guide/guide.scrbl +++ b/collects/scribblings/guide/guide.scrbl @@ -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"] diff --git a/collects/scribblings/guide/lists.scrbl b/collects/scribblings/guide/lists.scrbl index 03c2a3a696..d621d77c8f 100644 --- a/collects/scribblings/guide/lists.scrbl +++ b/collects/scribblings/guide/lists.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{=}] diff --git a/collects/scribblings/guide/welcome.scrbl b/collects/scribblings/guide/welcome.scrbl index ac9d690c8c..70a6ba9c5e 100644 --- a/collects/scribblings/guide/welcome.scrbl +++ b/collects/scribblings/guide/welcome.scrbl @@ -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} diff --git a/collects/scribblings/quick/quick.scrbl b/collects/scribblings/quick/quick.scrbl index 7e1d7f41b8..b2a5cff186 100644 --- a/collects/scribblings/quick/quick.scrbl +++ b/collects/scribblings/quick/quick.scrbl @@ -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] diff --git a/collects/scribblings/reference/match-grammar.ss b/collects/scribblings/reference/match-grammar.ss index a49ff67345..e41ef7b5d3 100644 --- a/collects/scribblings/reference/match-grammar.ss +++ b/collects/scribblings/reference/match-grammar.ss @@ -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])) diff --git a/collects/scribblings/reference/match.scrbl b/collects/scribblings/reference/match.scrbl index ee6c70ef9b..7d8c431508 100644 --- a/collects/scribblings/reference/match.scrbl +++ b/collects/scribblings/reference/match.scrbl @@ -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?].} diff --git a/collects/scribblings/reference/mz.ss b/collects/scribblings/reference/mz.ss index 6eedede78f..41ff3a1523 100644 --- a/collects/scribblings/reference/mz.ss +++ b/collects/scribblings/reference/mz.ss @@ -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 diff --git a/collects/scribblings/reference/pairs-scrbl.scrbl b/collects/scribblings/reference/pairs-scrbl.scrbl index 668a68bc8a..12eec7578b 100644 --- a/collects/scribblings/reference/pairs-scrbl.scrbl +++ b/collects/scribblings/reference/pairs-scrbl.scrbl @@ -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.} diff --git a/collects/scribblings/reference/reference.scrbl b/collects/scribblings/reference/reference.scrbl index e56e93f76b..78eb7e285b 100644 --- a/collects/scribblings/reference/reference.scrbl +++ b/collects/scribblings/reference/reference.scrbl @@ -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"] diff --git a/collects/scribblings/reference/to-do.ss b/collects/scribblings/reference/to-do.ss index ac8dec07f3..d94d5bf0de 100644 --- a/collects/scribblings/reference/to-do.ss +++ b/collects/scribblings/reference/to-do.ss @@ -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)))