From eeaa856ff139c871299f9452402733cd7bf18269 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 5 Jun 2007 06:44:39 +0000 Subject: [PATCH] reference-manual work svn: r6480 --- collects/scribble/manual.ss | 79 +++-- collects/scribble/scheme.ss | 20 +- collects/scribblings/guide/for.scrbl | 2 +- collects/scribblings/guide/lists.scrbl | 2 +- .../scribblings/guide/void-and-undef.scrbl | 18 +- collects/scribblings/reference/data.scrbl | 6 +- collects/scribblings/reference/derived.scrbl | 250 +++++++++++++++ collects/scribblings/reference/model.scrbl | 14 +- collects/scribblings/reference/numbers.scrbl | 2 +- .../scribblings/reference/reference.scrbl | 1 + collects/scribblings/reference/syntax.scrbl | 297 ++++++++++++++---- collects/scribblings/scribble/manual.scrbl | 6 +- 12 files changed, 572 insertions(+), 125 deletions(-) create mode 100644 collects/scribblings/reference/derived.scrbl diff --git a/collects/scribble/manual.ss b/collects/scribble/manual.ss index 4cc64b0040..fee088bf77 100644 --- a/collects/scribble/manual.ss +++ b/collects/scribble/manual.ss @@ -137,12 +137,14 @@ ;; ---------------------------------------- - (provide defproc defproc* defstruct defthing defform defform/none + (provide defproc defproc* defstruct defthing defform defform* defform/none specsubform specsubform/inline - var svar void-const) + var svar void-const undefined-const) - (define (void-const) - (schemefont "#")) + (define void-const + (schemeresultfont "#")) + (define undefined-const + (schemeresultfont "#")) (define dots0 (make-element #f (list "..."))) @@ -161,9 +163,9 @@ (syntax-rules () [(_ name fields desc ...) (*defstruct 'name 'fields (lambda () (list desc ...)))])) - (define-syntax (defform stx) + (define-syntax (defform* stx) (syntax-case stx () - [(_ spec desc ...) + [(_ [spec spec1 ...] desc ...) (with-syntax ([new-spec (syntax-case #'spec () [(name . rest) @@ -174,11 +176,17 @@ #'name) #'rest) #'spec)])]) - #'(*defform #t 'spec (lambda (x) (schemeblock0 new-spec)) (lambda () (list desc ...))))])) + #'(*defforms #t '(spec spec1 ...) + (list (lambda (x) (schemeblock0 new-spec)) + (lambda (ignored) (schemeblock0 spec1)) ...) + (lambda () (list desc ...))))])) + (define-syntax (defform stx) + (syntax-case stx () + [(_ spec desc ...) #'(defform* [spec] desc ...)])) (define-syntax (defform/none stx) (syntax-case stx () [(_ spec desc ...) - #'(*defform #f 'spec (lambda (ignored) (schemeblock0 spec)) (lambda () (list desc ...)))])) + #'(*defforms #f '(spec) (list (lambda (ignored) (schemeblock0 spec))) (lambda () (list desc ...)))])) (define-syntax specsubform (syntax-rules () [(_ spec desc ...) @@ -383,35 +391,42 @@ (define (meta-symbol? s) (memq s '(... ...+ ?))) - (define (*defform kw? form form-proc content-thunk) + (define (*defforms kw? forms form-procs content-thunk) (parameterize ([current-variable-list - (let loop ([form (if kw? (cdr form) form)]) - (cond - [(symbol? form) (if (meta-symbol? form) - null - (list form))] - [(pair? form) (append (loop (car form)) - (loop (cdr form)))] - [else null]))]) + (apply + append + (map (lambda (form) + (let loop ([form (if kw? (cdr form) form)]) + (cond + [(symbol? form) (if (meta-symbol? form) + null + (list form))] + [(pair? form) (append (loop (car form)) + (loop (cdr form)))] + [else null]))) + forms))]) (make-splice (cons (make-table 'boxed - (list - (list (make-flow - (list - ((or form-proc - (lambda (x) - (make-paragraph - (list - (to-element - `(,x - . ,(cdr form))))))) - (and kw? - (make-target-element - #f - (list (to-element (car form))) - (register-scheme-form-definition (car form)))))))))) + (map (lambda (form form-proc) + (list + (make-flow + (list + ((or form-proc + (lambda (x) + (make-paragraph + (list + (to-element + `(,x + . ,(cdr form))))))) + (and kw? + (eq? form (car forms)) + (make-target-element + #f + (list (to-element (car form))) + (register-scheme-form-definition (car form))))))))) + forms form-procs)) (content-thunk))))) (define (*specsubform form form-thunk content-thunk) diff --git a/collects/scribble/scheme.ss b/collects/scribble/scheme.ss index a334090051..6a2116d70e 100644 --- a/collects/scribble/scheme.ss +++ b/collects/scribble/scheme.ss @@ -28,19 +28,19 @@ (define opt-color "schemeopt") (define current-keyword-list - (make-parameter '(define let let* letrec require provide let-values - lambda new send if cond begin else and or + (make-parameter '(define require provide + new send if cond begin else and or define-syntax syntax-rules define-struct quote quasiquote unquote unquote-splicing syntax quasisyntax unsyntax unsyntax-splicing - for/fold for/list for*/list for for/and for/or for* for*/or for*/and for*/fold - for-values for*/list-values for/first for/last set!))) (define current-variable-list (make-parameter null)) (define defined-names (make-hash-table)) + (define-struct (sized-element element) (length)) + (define (typeset c multi-line? prefix1 prefix color?) (let* ([c (syntax-ize c 0)] [content null] @@ -63,7 +63,10 @@ (define out (case-lambda [(v cls) - (out v cls (if (string? v) (string-length v) 1))] + (out v cls (cond + [(string? v) (string-length v)] + [(sized-element? v) (sized-element-length v)] + [else 1]))] [(v cls len) (unless (equal? v "") (if (equal? v "\n") @@ -125,12 +128,13 @@ (datum->syntax-object a (let ([val? (positive? quote-depth)]) - (make-element + (make-sized-element (if val? value-color #f) (list (make-element (if val? value-color paren-color) '(". ")) (typeset a #f "" "" (not val?)) - (make-element (if val? value-color paren-color) '(" ."))))) + (make-element (if val? value-color paren-color) '(" ."))) + (+ (syntax-span a) 4))) (list (syntax-source a) (syntax-line a) (- (syntax-column a) 2) @@ -327,7 +331,7 @@ (out (if (and (identifier? c) color? (quote-depth . <= . 0) - (not (or it? is-kw? is-var?))) + (not (or it? is-var?))) (make-delayed-element (lambda (renderer sec ht) (let* ([vtag (register-scheme-definition (syntax-e c))] diff --git a/collects/scribblings/guide/for.scrbl b/collects/scribblings/guide/for.scrbl index 36410e7de7..c46ed72fde 100644 --- a/collects/scribblings/guide/for.scrbl +++ b/collects/scribblings/guide/for.scrbl @@ -214,7 +214,7 @@ This pruning behavior of @scheme[#:when] is more useful with @scheme[for/list] than @scheme[for]. Whereas a plain @scheme[when] form normally suffices with @scheme[for], a @scheme[when] expression form in a @scheme[for/list] would cause the result list to contain -@void-const[]s instead of omitting list elements. +@|void-const|s instead of omitting list elements. The @scheme[for*/list] is like @scheme[for*], nesting multiple iterations: diff --git a/collects/scribblings/guide/lists.scrbl b/collects/scribblings/guide/lists.scrbl index ecdff502ca..4a77a27563 100644 --- a/collects/scribblings/guide/lists.scrbl +++ b/collects/scribblings/guide/lists.scrbl @@ -189,7 +189,7 @@ simpler (just a procedure call). We have ignored several other variants of the interation form---including plain @scheme[for], which is used when the iteration body is to be run only for its effect. For more complete information, -see @secref["iterations+comprehensions"]. +see @secref["for"]. @;------------------------------------------------------------------------ @section{List Iteration from Scratch} diff --git a/collects/scribblings/guide/void-and-undef.scrbl b/collects/scribblings/guide/void-and-undef.scrbl index 2c634f1fbd..c929e72c91 100644 --- a/collects/scribblings/guide/void-and-undef.scrbl +++ b/collects/scribblings/guide/void-and-undef.scrbl @@ -8,14 +8,14 @@ Some procedures or expression forms have no need for a result value. For example, the @scheme[display] procedure is called only for the side-effect of writing output. In such cases the reslt value is -normally a special constant that prints as @void-const[]. When the -result of an expression is simply @void-const[], the REPL does not +normally a special constant that prints as @|void-const|. When the +result of an expression is simply @|void-const|, the REPL does not print anything. The @scheme[void] procedure takes any number of arguments and returns -@void-const[]. (That is, the identifier @schemeidfont{void} is bound -to a procedure that returns @void-const[], instead of being bound -directly to @void-const[].) +@|void-const|. (That is, the identifier @schemeidfont{void} is bound +to a procedure that returns @|void-const|, instead of being bound +directly to @|void-const|.) @examples[ (void) @@ -23,16 +23,16 @@ directly to @void-const[].) (list (void)) ] -A constant that prints as @schemefont{#} is used as the -result of a reference to a local binding when the binding is not yet +A constant that prints as @undefined-const is used as the result of a +reference to a local binding when the binding is not yet initialized. Such early references are not possible for bindings that corerspond to procedure arguments, @scheme[let] bindings, or @scheme[let*] bindings; early reference requires a recursive binding context, such as @scheme[letrec] or local @scheme[define]s in a procedure body. Also, early references to top-level and module top-level bindings raise an exception, instead of producing -@schemefont{#}. For these reasons, -@schemefont{#} rarely appears. +@|undefined-const|. For these reasons, @undefined-const rarely +appears. @def+int[ (define (strange) diff --git a/collects/scribblings/reference/data.scrbl b/collects/scribblings/reference/data.scrbl index e64b6cfcc5..b725d52dfa 100644 --- a/collects/scribblings/reference/data.scrbl +++ b/collects/scribblings/reference/data.scrbl @@ -1,7 +1,7 @@ #reader(lib "docreader.ss" "scribble") @require["mz.ss"] -@title[#:style 'toc]{Built-In Datatypes} +@title[#:style 'toc]{Core Datatypes and Procedures} Each of the built-in datatypes comes with a set of procedures for manipulating members of the datatype. @@ -196,10 +196,10 @@ If the @scheme[lst]s are empty, then @scheme[#f] is returned.} @; ---------------------------------------------------------------------- @section[#:tag "void"]{Void and Undefined} -@defproc[(void [v any/c] ...) void?]{Returns the constant @void-const[]. Each +@defproc[(void [v any/c] ...) void?]{Returns the constant @|void-const|. Each @scheme[v] argument is ignored.} @defproc[(void? [v any/c]) void?]{Returns @scheme[#t] if @scheme[v] is the - constant @void-const[], @scheme[#f] otherwise.} + constant @|void-const|, @scheme[#f] otherwise.} diff --git a/collects/scribblings/reference/derived.scrbl b/collects/scribblings/reference/derived.scrbl new file mode 100644 index 0000000000..c755ec6054 --- /dev/null +++ b/collects/scribblings/reference/derived.scrbl @@ -0,0 +1,250 @@ +#reader(lib "docreader.ss" "scribble") +@require["mz.ss"] + +@title[#:tag "mz:derived-syntax"]{Derived Syntactic Forms} + +@section{Iterations and Comprehensions: @scheme[for], @scheme[for/list], ...} + +@defform[(for (for-clause ...) . body)]{ + +Iteratively evaluates @scheme[body]. The @scheme[for-clause]s +introduce bindings whose scope inculdes @scheme[body] and that +determine the number of times that @scheme[body] is evaluated. + +In the simple case, each @scheme[for-clause] has the form + +@specsubform[[id seq-expr]]{} + +In this case, the @scheme[_seq-expr]s are evaluated left-to-right, and +each must produce a sequence value (see @secref["mz:sequences"]). The +@scheme[for] form iterates by drawing an element from each sequence; +if any sequence is empty, then the iteration stops, and @|void-const| +is the result of the @scheme[for] expression. Otherwise a location is +created for each @scheme[_id] to hold the corresponding element. The +@scheme[_id]s are then bound in the @scheme[body], which is evaluated, +and whose result(s) is(are) ignored. Iteration continues with the next +element in each sequence and with fresh locations for each +@scheme[_id]. Zero @scheme[for-clause]s is equivalent to a single +@scheme[for-clause] that binds an unreferenced @scheme[_id] to a +sequence containing one element. All of the @scheme[_id]s must be +distinct according to @scheme[bound-identifier=?]. + +If any @scheme[for-clause] has the form + +@specsubform[(code:line #:when guard-expr)]{} + +then only the preceding clauses (containing no @scheme[#:when]) +determine iteration as above, and the @scheme[body] is effectively +wrapped as + +@schemeblock[ +(when guard-expr + (for (for-clause ...) . body)) +] + +using the remaining @scheme[for-clauses]. + +@examples[ +(for ([i '(1 2 3)] + [j "abc"] + #:when (odd? i) + [k #2(#t #f)]) + (display (list i j k))) +(for () + (display "here")) +(for ([i '()]) + (error "doesn't get here")) +]} + +@defform[(for/list (for-clause ...) . body)]{ Iterates like +@scheme[for], but that the last expression of @scheme[body] must +produce a single value, and the result of the @scheme[for/list] +expression is a list of the results in order. + +@examples[ +(for/list ([i '(1 2 3)] + [j "abc"] + #:when (odd? i) + [k #2(#t #f)]) + (list i j k)) +(for/list () 'any) +(for/list ([i '()]) + (error "doesn't get here")) +]} + +@defform[(for/and (for-clause ...) . body)]{ Iterates like +@scheme[for], but when last expression of @scheme[body] produces +@scheme[#f], then iteration terminates, and the result of the +@scheme[for/and] expression is @scheme[#f]. If the @scheme[body] +is never evaluated, then the result of the @scheme[for/and] +expression is @scheme[#t]. Otherwise, the result is the (single) +result from the last evaluation of @scheme[body]. + +@examples[ +(for/and ([i '(1 2 3 "x")]) + (i . < . 3)) +(for/and ([i '(1 2 3 4)]) + i) +(for/and ([i '()]) + (error "doesn't get here")) +]} + +@defform[(for/or (for-clause ...) . body)]{ Iterates like +@scheme[for], but when last expression of @scheme[body] produces +a value other than @scheme[#f], then iteration terminates, and +the result of the @scheme[for/or] expression is the same +(single) value. If the @scheme[body] is never evaluated, then the +result of the @scheme[for/or] expression is +@scheme[#f]. Otherwise, the result is @scheme[#f]. + +@examples[ +(for/or ([i '(1 2 3 "x")]) + (i . < . 3)) +(for/or ([i '(1 2 3 4)]) + i) +(for/or ([i '()]) + (error "doesn't get here")) +]} + +@defform[(for/first (for-clause ...) . body)]{ Iterates like +@scheme[for], but after @scheme[body] is evaluated the first +time, then the iteration terminates, and the @scheme[for/first] +result is the (single) result of @scheme[body]. If the +@scheme[body] is never evaluated, then the result of the +@scheme[for/first] expression is @scheme[#f]. + +@examples[ +(for/first ([i '(1 2 3 "x")] + #:when (even? i)) + (number->string i)) +(for/first ([i '()]) + (error "doesn't get here")) +]} + +@defform[(for/last (for-clause ...) . body)]{ Iterates like +@scheme[for], but the @scheme[for/last] result is the (single) +result of of the last evaluation of @scheme[body]. If the +@scheme[body] is never evaluated, then the result of the +@scheme[for/last] expression is @scheme[#f]. + +@examples[ +(for/last ([i '(1 2 3 4 5)] + #:when (even? i)) + (number->string i)) +(for/last ([i '()]) + (error "doesn't get here")) +]} + +@defform[(for/fold ([accum-id init-expr] ...) (for-clause ...). body)]{ + +Iterates like @scheme[for]. Before iteration starts, the +@scheme[init-expr]s are evaluated to produce initial accumulator +values. At the start of each out iteration, a location is generated +for each @scheme[accum-id], and the correspinding current accumulator +value is placed into the location. The last expression in +@scheme[body] must produce as many values as @scheme[accum-id]s, and +those values become the current accumulator values. When iteration +terminates, the result of the @scheme[fold/for] expression is(are) the +accumulator value(s). + +@examples[ +(for/fold ([sum 0] + [rev-roots null]) + ([i '(1 2 3 4)]) + (values (+ sum i) (cons (sqrt i) rev-roots))) +]} + +@defform[(for* (for-clause ...) . body)]{ +Like @scheme[for], but with an implicit @scheme[#:when #t] between +each pair of @scheme[for-clauses], so that all sequence iterations are +nested. + +@examples[ +(for* ([i '(1 2)] + [j "ab"]) + (display (list i j))) +]} + +@defform[(for*/list (for-clause ...) . body)]{ +Like @scheme[for/list], but with the implicit nesting of @scheme[for*]. +@examples[ +(for*/list ([i '(1 2)] + [j "ab"]) + (list i j)) +]} + +@defform[(for*/and (for-clause ...) . body)]{ +Like @scheme[for/and], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/or (for-clause ...) . body)]{ +Like @scheme[for/or], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/first (for-clause ...) . body)]{ +Like @scheme[for/first], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/last (for-clause ...) . body)]{ +Like @scheme[for/last], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/fold ([accum-id init-expr] ...) (for-clause ...) . body)]{ +Like @scheme[for/fold], but with the implicit nesting of @scheme[for*].} + +@defform[(for-values (for-values-clause ...) . body)]{ Like +@scheme[for], but each @scheme[for-values-clause] has one of the +following two forms: + + @specsubform[[(id ...) seq-expr]]{ The sequence produced by + @scheme[_seq-expr] must return as many values for each iteration as + @scheme[id]s, and the values are placed in the locations generated + for the @scheme[id]s.} + + @specsubform[(code:line #:when guard-expr)]{As in @scheme[for].} + +@examples[ +(for-values ([(i j) #hash(("a" . 1) ("b" . 20))]) + (display (list i j))) +]} + +@defform[(for/list-values (for-values-clause ...) . body)]{ Like +@scheme[for/list], but with multiple-value clauses like +@scheme[for-values].} + +@defform[(for/and-values (for-values-clause ...) . body)]{ Like +@scheme[for-and], but with multiple-value clauses like +@scheme[for-values].} + +@defform[(for/or-values (for-values-clause ...) . body)]{ Like +@scheme[for/or], but with multiple-value clauses like +@scheme[for-values].} + +@defform[(for/first-values (for-values-clause ...) . body)]{ Like +@scheme[for/first], but with multiple-value clauses like +@scheme[for-values].} + +@defform[(for/last-values (for-values-clause ...) . body)]{ Like +@scheme[for/last], but with multiple-value clauses like +@scheme[for-values].} + +@defform[(for/fold-values ([id expr] ...) (for-values-clause ...) . body)]{ Like +@scheme[for/fold], but with multiple-value clauses like +@scheme[for-values].} + +@defform[(for*-values (for-values-clause ...) . body)]{ +Like @scheme[for-values], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/list-values (for-values-clause ...) . body)]{ +Like @scheme[for/list-values], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/and-values (for-values-clause ...) . body)]{ +Like @scheme[for/and-values], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/or-values (for-values-clause ...) . body)]{ +Like @scheme[for/or-values], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/first-values (for-values-clause ...) . body)]{ +Like @scheme[for/first-values], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/last-values (for-values-clause ...) . body)]{ +Like @scheme[for/last-values], but with the implicit nesting of @scheme[for*].} + +@defform[(for*/fold-values ([id expr] ...) (for-values-clause ...) . body)]{ +Like @scheme[for/fold-values], but with the implicit nesting of @scheme[for*].} diff --git a/collects/scribblings/reference/model.scrbl b/collects/scribblings/reference/model.scrbl index 2a0427e250..f0160b627b 100644 --- a/collects/scribblings/reference/model.scrbl +++ b/collects/scribblings/reference/model.scrbl @@ -177,7 +177,7 @@ right-hand expression must be reduced to a value. [{} (begin (code:hilite (define x 10)) (+ x 1))] [{(define x 10)} - (code:hilite (begin #,(void-const) (+ x 1)))] + (code:hilite (begin #,void-const (+ x 1)))] [{(define x 10)} (+ (code:hilite x) 1)] [{(define x 10)} @@ -197,7 +197,7 @@ existing top-level binding: [{(define x 10)} (begin (code:hilite (set! x 8)) x)] [{(define x 8)} - (code:hilite (begin #,(void-const) x))] + (code:hilite (begin #,void-const x))] [{(define x 8)} (code:hilite x)] [{(define x 8)} @@ -217,7 +217,7 @@ values, which are the results of expressions, and @defterm{objects}, which hold the data referenced by a value. A few kinds of objects can serve directly as values, including -booleans, @void-const[], and small exact integers. More generally, +booleans, @|void-const|, and small exact integers. More generally, however, a value is a reference to an object. For example, a value can be a reference to a particular vector that currently holds the value @scheme[10] in its first slot. If an object is modified, then the @@ -243,7 +243,7 @@ create objects, such as @scheme[vector], add to the set of objects: (vector-ref y 0))] [{(define #(10 20))} {(define x )} - (code:hilite (begin #,(void-const) + (code:hilite (begin #,void-const (define y x) (vector-set! x 0 11) (vector-ref y 0)))] @@ -260,7 +260,7 @@ create objects, such as @scheme[vector], add to the set of objects: [{(define #(10 20))} {(define x ) (define y )} - (code:hilite (begin #,(void-const) + (code:hilite (begin #,void-const (vector-set! x 0 11) (vector-ref y 0)))] [{(define #(10 20))} @@ -276,7 +276,7 @@ create objects, such as @scheme[vector], add to the set of objects: [{(define #(11 20))} {(define x ) (define y )} - (code:hilite (begin #,(void-const) + (code:hilite (begin #,void-const (vector-ref y 0)))] [{(define #(11 20))} {(define x ) @@ -432,7 +432,7 @@ the variable is always replaced with a location by the time the [{(define (lambda (x) (begin (set! x 3) x)))} {(define f ) (define xloc 3)} - (code:hilite (begin #,(void-const) xloc))] + (code:hilite (begin #,void-const xloc))] [{(define (lambda (x) (begin (set! x 3) x)))} {(define f ) (define xloc 3)} diff --git a/collects/scribblings/reference/numbers.scrbl b/collects/scribblings/reference/numbers.scrbl index a1107e6565..33892b86fe 100644 --- a/collects/scribblings/reference/numbers.scrbl +++ b/collects/scribblings/reference/numbers.scrbl @@ -388,7 +388,7 @@ noted above). Two numbers are @scheme[equal?] when they are @; ------------------------------------------------------------------------ -@section{Trigonometric Functions} +@section{Trignometric Functions} @defproc[(sin [z number?]) number?]{ Returns the sine of @scheme[z], where @scheme[z] is in radians. diff --git a/collects/scribblings/reference/reference.scrbl b/collects/scribblings/reference/reference.scrbl index 468d6c4afb..6709834523 100644 --- a/collects/scribblings/reference/reference.scrbl +++ b/collects/scribblings/reference/reference.scrbl @@ -15,6 +15,7 @@ language. @include-section["read.scrbl"] @include-section["macros.scrbl"] @include-section["syntax.scrbl"] +@include-section["derived.scrbl"] @include-section["data.scrbl"] @index-section["mzscheme-index"] diff --git a/collects/scribblings/reference/syntax.scrbl b/collects/scribblings/reference/syntax.scrbl index 3681e626b6..8b9808b18e 100644 --- a/collects/scribblings/reference/syntax.scrbl +++ b/collects/scribblings/reference/syntax.scrbl @@ -1,11 +1,23 @@ #reader(lib "docreader.ss" "scribble") @require["mz.ss"] -@title[#:tag "mz:syntax"]{Core Syntactic Forms} +@title[#:tag "mz:syntax" #:style 'toc]{Core Syntactic Forms} -A syntactic form is described by a BNF-like notation that describes a -combination of (syntax-wrapped) pairs, symbols, and other data (not a -sequence of characters): +This section describes core syntax forms that apear in a fully +expanded expression, plus a few closely-related non-core forms. + +@local-table-of-contents[] + +@subsubsub*section{Notation} + +Each syntactic form is described by a BNF-like notation that describes +a combination of (syntax-wrapped) pairs, symbols, and other data (not +a sequence of characters). These grammatical specifications are shown +as follows: + +@specsubform[(#, @schemekeywordfont{some-form} id ...)] + +Within such specifications, @itemize{ @@ -18,61 +30,86 @@ sequence of characters): @item{@scheme[?] means zero instances or one instance of the preceding datum.} - @item{Italic sequences of characters play the role of non-terminals. In - particular: + @item{italic meta-identifier play the role of non-terminals; in + particular, @itemize{ - @item{A sequence that ends in @scheme[_id] refers to a + @item{a meta-identifier that ends in @scheme[_id] stands for a syntax-wrapped symbol.} - @item{A sequence that ends in @scheme[_keyword] refers to a - syntax-wrapped keyword.} + @item{a meta-identifier that ends in @scheme[_keyword] stands + for a syntax-wrapped keyword.} - @item{A sequence that end with @scheme[_expr] refers to a sub-form - that is expanded as an expression.} - }} -} + @item{a meta-identifier that ends with @scheme[_expr] stands + for a sub-form that is expanded as an expression.} + + @item{a meta-identifier that ends with @scheme[_body] stands + for a non-empty syntax-wrapped list of sub-forms; the + list is expanded as internal-definition sequence + followed by at least one expression (see + @secref["intdef-body"] for details).} + + }} } @;------------------------------------------------------------------------ -@section{Variable Reference} +@section{Variable References and @scheme[#%top]} @defform/none[id]{ -A reference to a module-level or local binding, when @scheme[id] is +Refers to a module-level or local binding, when @scheme[id] is not bound as a transformer (see @secref["mz:expansion"]). At run-time, the reference evaluates to the value in the location associated with the binding. When the expander encounters an @scheme[id] that is not bound by a -module or local binding, it converts the expression to @scheme[(#%top -. id)].} +module or local binding, it converts the expression to @scheme[(#, +@schemeidfont{#%top} . id)] giving @schemeidfont{#%top} the lexical +context of the @scheme[id]; typically, that context refers to +@scheme[#%top]. + +@examples[ +(define x 10) +x +(let ([x 5]) x) +((lambda (x) x) 2) +]} @defform[(#%top . id)]{ -A reference to a top-level definition that could bind @scheme[id], +Refers to a top-level definition that could bind @scheme[id], even if @scheme[id] has a local binding in its context. Such -references are disallowed anywhere within a @scheme[module] form.} +references are disallowed anywhere within a @scheme[module] form. + +@examples[ +(define x 12) +(let ([x 5]) (#%top . x)) +]} @;------------------------------------------------------------------------ -@section{Procedure Application} +@section{Procedure Applications and @scheme[#%app]} @defform/none[(proc-expr arg ...)]{ -A procedure application, normally, when @scheme[proc-expr] is not an +Applies a procedure, normally, when @scheme[proc-expr] is not an identifier that has a transformer binding (see @secref["mz:expansion"]). More precisely, the expander converts this form to @scheme[(#, -@schemeidfont{#%app} proc-expr arg ...)] using the lexical -context for @schemeidfont{#%app} that is associated with the original -form (i.e., the pair that combines @scheme[proc-expr] and its +@schemeidfont{#%app} proc-expr arg ...)], giving @schemeidfont{#%app} +the lexical context that is associated with the original form (i.e., +the pair that combines @scheme[proc-expr] and its arguments). Typically, the lexical context of the pair indicates the -procedure-application @scheme[#%app] that is described next.} +procedure-application @scheme[#%app] that is described next. + +@examples[ +(+ 1 2) +((lambda (x #:arg y) (list y x)) #:arg 2 1) +]} @defform[(#%app proc-expr arg ...)]{ -A procedure application. Each @scheme[arg] is one of the following: +Applies a procedure. Each @scheme[arg] is one of the following: @specsubform[arg-expr]{The resulting value is a non-keyword argument.} @@ -85,7 +122,7 @@ The @scheme[proc-expr] and @scheme[_arg-expr]s are evaluated in order, left to right. If the result of @scheme[proc-expr] is a procedure that accepts as many arguments as non-@scheme[_keyword] @scheme[_arg-expr]s, if it accepts arguments for all of the -e@scheme[_keyword]s in the application, and if all required +@scheme[_keyword]s in the application, and if all required keyword-based arguments are represented among the @scheme[_keyword]s in the application, then the procedure is called with the values of the @scheme[arg-expr]s. Otherwise, the @exnraise[exn:fail:contract]. @@ -96,20 +133,26 @@ expression is(are) the result(s) of the procedure. The relative order of @scheme[_keyword]-based arguments matters only for the order of @scheme[_arg-expr] evaluations; the arguments are -regonized by the applied procedure based on the @scheme[_keyword], and -not their positions. The other @scheme[_arg-expr] values, in contrast, -are recognized by the applied procedure according to their order in -the application form.} +associated with argument variables in the applied procedure based on +the @scheme[_keyword]s, and not their positions. The other +@scheme[_arg-expr] values, in contrast, are associated with variables +according to their order in the application form. + +@examples[ +(#%app + 1 2) +(#%app (lambda (x #:arg y) (list y x)) #:arg 2 1) +(#%app cons) +]} @;------------------------------------------------------------------------ -@section{Procedure Expression: @scheme[lambda] and @scheme[case-lambda]} +@section{Procedure Expressions: @scheme[lambda] and @scheme[case-lambda]} -@defform[(lambda formals* body-expr ...+)]{ +@defform[(lambda formals* . body)]{ -An expression that procedures a procedure. The @scheme[formals*] -determines the number of arguments that the procedure accepts. It is -either a simple @scheme[_formals], or one of the extended forms. +Procedures a procedure. The @scheme[formals*] determines the number of +arguments that the procedure accepts. It is either a simple +@scheme[_formals], or one of the extended forms. A simple @scheme[_formals] has one of the following three forms: @@ -128,11 +171,11 @@ A simple @scheme[_formals] has one of the following three forms: arguments. All arguments are placed into a list that is associated with @scheme[rest-id].} -In addition to the form of a @scheme[_formals], a @scheme[formals*] -can be a sequence of @scheme[_formal*]s optionally ending with a +Besides the three @scheme[_formals] forms, a @scheme[formals*] can be +a sequence of @scheme[_formal-arg]s optionally ending with a @scheme[rest-id]: -@specsubform[(formal* ...)]{ Each @scheme[formal*] has the following +@specsubform[(formal-arg ...)]{ Each @scheme[formal-arg] has the following four forms: @specsubform[id]{Adds one to both the minimum and maximum @@ -145,7 +188,7 @@ can be a sequence of @scheme[_formal*]s optionally ending with a @scheme[id] is associated with an actual argument by position, and if no such argument is provided, the @scheme[default-expr] is evaluated to produce a value associated with @scheme[id]. - No @scheme[formal*] with a @scheme[default-expr] can appear + No @scheme[formal-arg] with a @scheme[default-expr] can appear before an @scheme[id] without a @scheme[default-expr] and without a @scheme[keyword].} @@ -161,25 +204,26 @@ can be a sequence of @scheme[_formal*]s optionally ending with a otherwise, the @scheme[default-expr] is evaluated to obtain a value to associate with @scheme[id].} - The position of a @scheme[_keyword] @scheme[formal*] in + The position of a @scheme[_keyword] @scheme[formal-arg] in @scheme[formals*] does not matter, but each specified @scheme[_keyword] must be distinct.} -@specsubform[(formal* ...+ . rest-id)]{ Like the previous case, but +@specsubform[(formal-arg ...+ . rest-id)]{ Like the previous case, but the procedure accepts any number of non-keyword arguments - beyond its minimum number of arguments. When more arguments are - provided than non-@scheme[_keyword] arguments among the @scheme[formal*]s, - the extra arguments are placed into a list that is associated to - @scheme[rest-id].} + beyond its minimum number of arguments. When more arguments are + provided than non-@scheme[_keyword] arguments among the + @scheme[formal-arg]s, the extra arguments are placed into a + list that is associated to @scheme[rest-id].} -The @scheme[formals*] identifiers are bound in the -@scheme[body-expr]s. When the procedure is applied, a new location is -created for each identifier, and the location is filled with the -associated argument value. +The @scheme[formals*] identifiers are bound in the @scheme[body]. (See +@secref["intdef-body"] for information on @scheme[body] forms.) When +the procedure is applied, a new location is created for each +identifier, and the location is filled with the associated argument +value. -If any identifier appears in @scheme[body-expr]s that is not one of -the identifiers in @scheme[formals*], then it refers to the same -location that it would if it appears in place of the @scheme[lambda] +If any identifier appears in @scheme[body] that is not one of the +identifiers in @scheme[formals*], then it refers to the same location +that it would if it appeared in place of the @scheme[lambda] expression. (In other words, variable reference is lexically scoped.) When multiple identifiers appear in a @scheme[formals*], they must be @@ -189,14 +233,25 @@ If the procedure procedure by @scheme[lambda] is applied to fewer or more arguments than it accepts, the @exnraise[exn:fail:contract]. If @scheme[formals*] includes @scheme[keyword]s and an application includes too few arguments before the keyword section, the same -keyword in multiple odd positions of the keyword section, or a keyword -that is not among the @scheme[formals*] @scheme[keyword]s in an odd -position of the keyword section, then the -@exnraise[exn:fail:contract].} +keyword in multiple positions, or a keyword that is not among the +@scheme[formals*] @scheme[_keyword]s, then the +@exnraise[exn:fail:contract]. -@defform[(case-lambda [formals body-expr ...+] ...)]{ +The last expression in @scheme[body] is in tail position with respect +to the procedure body. -An expression that procedure. Each @scheme[[forms body-expr ...+]] +@examples[ +((lambda (x) x) 10) +((lambda (x y) (list y x)) 1 2) +((lambda (x [y 5]) (list y x)) 1 2) +(let ([f (lambda (x #:arg y) (list y x))]) + (list (f 1 #:arg 2) + (f #:arg 2 1))) +]} + +@defform[(case-lambda [formals . body] ...)]{ + +Produces a procedure. Each @scheme[[forms body]] clause is analogous to a single @scheme[lambda] procedure; applying the @scheme[case-lambda]-generated procedure is the same as applying a procedure that corresponds to one of the clauses---the first procedure @@ -207,4 +262,126 @@ procedure accepts the given number of arguments, the Note that a @scheme[case-lambda] clause supports only @scheme[formals], not the more general @scheme[_formals*] of @scheme[lambda]. That is, @scheme[case-lambda] does not directly -support keyword and optional arguments for an inidvidual clause.} +support keyword and optional arguments. + +@examples[ +(let ([f (case-lambda + [() 10] + [(x) x] + [(x y) (list y x)] + [r r])]) + (list (f) + (f 1) + (f 1 2) + (f 1 2 3))) +]} + +@;------------------------------------------------------------------------ +@section{Local Binding: @scheme[let], @scheme[let*], and @scheme[letrec]} + +@defform*[[(let ([id val-expr] ...) . body) + (let proc-id ([id init-expr] ...) . body)]]{ + +The first form evaluates the @scheme[val-expr]s left-to-right, creates +a new location for each @scheme[id], and places the values into the +locations. It then evaluates the @scheme[body], in which the +@scheme[id]s are bound. (See @secref["intdef-body"] for information +on @scheme[body] forms.) The last expression in @scheme[body] is in +tail position with respect to the @scheme[let] form. The @scheme[id]s +must be distinct according to @scheme[bound-identifier=?]. + +@examples[ +(let ([x 5]) x) +(let ([x 5]) + (let ([x 2] + [y x]) + (list y x))) +] + +The second form evaluates the @scheme[init-expr]s; the resulting +values become arguments in an application of a procedure +@scheme[(lambda (id ...) . body)], where @scheme[proc-id] is bound +within @scheme[body] to the procedure itself.} + +@examples[ +(let fac ([n 10]) + (if (zero? n) + 1 + (* n (fac (sub1 n))))) +] + +@defform[(let* ([id val-expr] ...) . body)]{ + +Similar to @scheme[let], but evaluates the @scheme[val-expr]s one by +one, creating a location for each @scheme[id] as soon as the value is +available, and binding @scheme[id] in the remaining @scheme[val-expr]s +as well as the @scheme[body]. The @scheme[id]s need not be distinct. + +@examples[ +(let ([x 1] + [y (+ x 1)]) + (list y x)) +]} + +@defform[(letrec ([id val-expr] ...) . body)]{ + +Similar to @scheme[let], but the locations for all @scheme[id]s are +created first and filled with @|undefined-const|, and all +@scheme[id]s are bound in all @scheme[val-expr]s as well as +@scheme[body]. The @scheme[id]s must be distinct according to +@scheme[bound-identifier=?]. + +@examples[ +(letrec ([is-even? (lambda (n) + (or (zero? n) + (is-odd? (sub1 n))))] + [is-odd? (lambda (n) + (or (= n 1) + (is-even? (sub1 n))))]) + (is-odd? 11)) +]} + +@defform[(let-values ([(id ...) val-expr] ...) . body)]{ Like +@scheme[let], except that each @scheme[val-expr] must produce as many +values as corresponding @scheme[id]s. A separate location is created +for each @scheme[id], all of which are bound in the @scheme[body]. + +@examples[ +(let-values ([(x y) (quotient/remainder 10 3)]) + (list y x)) +]} + +@defform[(let*-values ([(id ...) val-expr] ...) . body)]{ Like +@scheme[let*], except that each @scheme[val-expr] must produce as many +values as corresponding @scheme[id]s. A separate location is created +for each @scheme[id], all of which are bound in the later +@scheme[val-expr]s and in the @scheme[body]. + +@examples[ +(let*-values ([(x y) (quotient/remainder 10 3)] + [(z) (list y x)]) + z) +]} + +@defform[(letrec-values ([(id ...) val-expr] ...) . body)]{ Like +@scheme[letrec], except that each @scheme[val-expr] must produce as +many values as corresponding @scheme[id]s. A separate location is +created for each @scheme[id], all of which are initialized to +@|undefined-const| and bound in all @scheme[val-expr]s +and in the @scheme[body]. + +@examples[ +(letrec-values ([(is-even? is-odd?) + (values + (lambda (n) + (or (zero? n) + (is-odd? (sub1 n)))) + (lambda (n) + (or (= n 1) + (is-even? (sub1 n)))))]) + (is-odd? 11)) +]} + +@;------------------------------------------------------------------------ +@section{Sequencing: @scheme[begin]} + diff --git a/collects/scribblings/scribble/manual.scrbl b/collects/scribblings/scribble/manual.scrbl index fccc359c76..364d50148f 100644 --- a/collects/scribblings/scribble/manual.scrbl +++ b/collects/scribblings/scribble/manual.scrbl @@ -307,9 +307,9 @@ for the index entry.} @defthing[PLaneT string?]{@scheme["PLaneT"] (to help make sure you get the letters in the right case).} -@defproc[(void-const) any/c]{Returns @scheme["void"], as opposed to -@scheme[(scheme void)]---but we may eventually find a clearer way to -refer to @void-const in prose.} +@defthing[void-const element?]{Returns an element for @|void-const|.} + +@defthing[undefined-const element?]{Returns an element for @|undefined-const|.} @defproc[(centerline [pre-flow any/c] ...0) table?]{Produces a centered table with the @scheme[pre-flow] parsed by