From 1477c7ec1b7e062ae8d40554322a21df537f10e3 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 18 Jun 2007 06:34:41 +0000 Subject: [PATCH] doc work svn: r6685 --- collects/scribble/eval.ss | 5 +- collects/scribble/manual.ss | 38 ++-- collects/scribble/scheme.ss | 6 +- collects/scribblings/guide/apply.scrbl | 12 +- collects/scribblings/guide/binding.scrbl | 8 +- collects/scribblings/guide/cond.scrbl | 163 +++++++++++++++++ collects/scribblings/guide/define.scrbl | 25 +-- collects/scribblings/guide/forms.scrbl | 17 +- collects/scribblings/guide/guide.scrbl | 7 + collects/scribblings/guide/lambda.scrbl | 10 +- collects/scribblings/guide/let.scrbl | 180 ++++++++++++++++++- collects/scribblings/guide/lists.scrbl | 8 +- collects/scribblings/guide/named-let.scrbl | 10 +- collects/scribblings/guide/ports.scrbl | 31 ++++ collects/scribblings/reference/derived.scrbl | 139 ++++++++++++++ collects/scribblings/reference/model.scrbl | 50 +++--- collects/scribblings/reference/syntax.scrbl | 153 ++++++++++++++-- 17 files changed, 763 insertions(+), 99 deletions(-) create mode 100644 collects/scribblings/guide/cond.scrbl create mode 100644 collects/scribblings/guide/ports.scrbl diff --git a/collects/scribble/eval.ss b/collects/scribble/eval.ss index 530827561e..db4105e371 100644 --- a/collects/scribble/eval.ss +++ b/collects/scribble/eval.ss @@ -215,12 +215,15 @@ (list " "))) (define-syntax (schemedefinput* stx) - (syntax-case stx (eval-example-string define define-struct) + (syntax-case stx (eval-example-string define define-values define-struct) [(_ (eval-example-string s)) #'(schemeinput* (eval-example-string s))] [(_ (define . rest)) (syntax-case stx () [(_ e) #'(schemeblock+line e)])] + [(_ (define-values . rest)) + (syntax-case stx () + [(_ e) #'(schemeblock+line e)])] [(_ (define-struct . rest)) (syntax-case stx () [(_ e) #'(schemeblock+line e)])] diff --git a/collects/scribble/manual.ss b/collects/scribble/manual.ss index d87a9bc4bd..1c5d438ad5 100644 --- a/collects/scribble/manual.ss +++ b/collects/scribble/manual.ss @@ -213,7 +213,7 @@ (*defstruct 'name 'fields (lambda () (list desc ...)))])) (define-syntax (defform*/subs stx) (syntax-case stx () - [(_ [spec spec1 ...] ([non-term-id non-term-form ...] ...) desc ...) + [(_ #:literals (lit ...) [spec spec1 ...] ([non-term-id non-term-form ...] ...) desc ...) (with-syntax ([new-spec (syntax-case #'spec () [(name . rest) @@ -224,7 +224,7 @@ #'name) #'rest) #'spec)])]) - #'(*defforms #t + #'(*defforms #t '(lit ...) '(spec spec1 ...) (list (lambda (x) (schemeblock0 new-spec)) (lambda (ignored) (schemeblock0 spec1)) ...) @@ -233,7 +233,9 @@ (lambda () (schemeblock0 non-term-form)) ...) ...) - (lambda () (list desc ...))))])) + (lambda () (list desc ...))))] + [(fm [spec spec1 ...] ([non-term-id non-term-form ...] ...) desc ...) + #'(fm #:literals () [spec spec1 ...] ([non-term-id non-term-form ...] ...) desc ...)])) (define-syntax (defform* stx) (syntax-case stx () [(_ [spec ...] desc ...) #'(defform*/subs [spec ...] () desc ...)])) @@ -242,41 +244,49 @@ [(_ spec desc ...) #'(defform*/subs [spec] () desc ...)])) (define-syntax (defform/subs stx) (syntax-case stx () + [(_ #:literals lits spec subs desc ...) #'(defform*/subs #:literals lits [spec] subs desc ...)] [(_ spec subs desc ...) #'(defform*/subs [spec] subs desc ...)])) (define-syntax (defform/none stx) (syntax-case stx () [(_ spec desc ...) - #'(*defforms #f + #'(*defforms #f null '(spec) (list (lambda (ignored) (schemeblock0 spec))) null null (lambda () (list desc ...)))])) (define-syntax specsubform (syntax-rules () + [(_ #:literals (lit ...) spec desc ...) + (*specsubform 'spec #f '(lit ...) (lambda () (schemeblock0 spec)) null null (lambda () (list desc ...)))] [(_ spec desc ...) - (*specsubform 'spec #f (lambda () (schemeblock0 spec)) null null (lambda () (list desc ...)))])) + (*specsubform 'spec #f null (lambda () (schemeblock0 spec)) null null (lambda () (list desc ...)))])) (define-syntax specspecsubform (syntax-rules () [(_ spec desc ...) (make-blockquote "leftindent" (list (specsubform spec desc ...)))])) (define-syntax specform (syntax-rules () + [(_ #:literals (lit ...) spec desc ...) + (*specsubform 'spec #t '(lit ...) (lambda () (schemeblock0 spec)) null null (lambda () (list desc ...)))] [(_ spec desc ...) - (*specsubform 'spec #t (lambda () (schemeblock0 spec)) null null (lambda () (list desc ...)))])) + (*specsubform 'spec #t null (lambda () (schemeblock0 spec)) null null (lambda () (list desc ...)))])) (define-syntax specform/subs (syntax-rules () - [(_ spec ([non-term-id non-term-form ...] ...) desc ...) + [(_ #:literals (lit ...) spec ([non-term-id non-term-form ...] ...) desc ...) (*specsubform 'spec #t + '(lit ...) (lambda () (schemeblock0 spec)) '((non-term-id non-term-form ...) ...) (list (list (lambda () (scheme non-term-id)) (lambda () (schemeblock0 non-term-form)) ...) ...) - (lambda () (list desc ...)))])) + (lambda () (list desc ...)))] + [(_ spec ([non-term-id non-term-form ...] ...) desc ...) + (specform/subs #:literals () spec ([non-term-id non-term-form ...] ...) desc ...)])) (define-syntax specsubform/inline (syntax-rules () [(_ spec desc ...) - (*specsubform 'spec #f #f null null (lambda () (list desc ...)))])) + (*specsubform 'spec #f null #f null null (lambda () (list desc ...)))])) (define-syntax defthing (syntax-rules () [(_ id result desc ...) @@ -495,7 +505,7 @@ (define (meta-symbol? s) (memq s '(... ...+ ?))) - (define (*defforms kw? forms form-procs subs sub-procs content-thunk) + (define (*defforms kw? lits forms form-procs subs sub-procs content-thunk) (parameterize ([current-variable-list (apply append @@ -503,7 +513,8 @@ (let loop ([form (cons (if kw? (cdr form) form) subs)]) (cond - [(symbol? form) (if (meta-symbol? form) + [(symbol? form) (if (or (meta-symbol? form) + (memq form lits)) null (list form))] [(pair? form) (append (loop (car form)) @@ -543,12 +554,13 @@ sub-procs)))) (content-thunk))))) - (define (*specsubform form has-kw? form-thunk subs sub-procs content-thunk) + (define (*specsubform form has-kw? lits form-thunk subs sub-procs content-thunk) (parameterize ([current-variable-list (append (let loop ([form (cons (if has-kw? (cdr form) form) subs)]) (cond - [(symbol? form) (if (meta-symbol? form) + [(symbol? form) (if (or (meta-symbol? form) + (memq form lits)) null (list form))] [(pair? form) (append (loop (car form)) diff --git a/collects/scribble/scheme.ss b/collects/scribble/scheme.ss index 28570a0aad..34cfa4a279 100644 --- a/collects/scribble/scheme.ss +++ b/collects/scribble/scheme.ss @@ -34,7 +34,7 @@ ;; This is temporary, until the MzScheme manual is filled in... (make-parameter '(define require provide define-values begin0 when unless - new send if cond begin else and or + new send if cond begin else => and or define-syntax syntax-rules define-struct quote quasiquote unquote unquote-splicing syntax quasisyntax unsyntax unsyntax-splicing @@ -377,14 +377,14 @@ value-color] [(identifier? c) (cond + [is-var? + variable-color] [(and (identifier? c) (memq (syntax-e c) (current-keyword-list))) keyword-color] [(and (identifier? c) (memq (syntax-e c) (current-meta-list))) meta-color] - [is-var? - variable-color] [it? variable-color] [else symbol-color])] [else paren-color]) diff --git a/collects/scribblings/guide/apply.scrbl b/collects/scribblings/guide/apply.scrbl index 3d036d72be..3365a53c2d 100644 --- a/collects/scribblings/guide/apply.scrbl +++ b/collects/scribblings/guide/apply.scrbl @@ -20,7 +20,7 @@ bound as a syntax transformer (such as @scheme[if] or A function call is evaluated by first evaluating the @scheme[_proc-expr] and all @scheme[_arg-expr]s in order (left to -right). Then, if @scheme[_proc-expr] produced a function that accepts +right). Then, if @scheme[_proc-expr] produces a function that accepts as many arguments as supplied @scheme[_arg-expr]s, the function is called. Otherwise, an exception is raised. @@ -32,11 +32,11 @@ called. Otherwise, an exception is raised. ] Some functions, such as @scheme[cons], accept a fixed number of -arguments. Some functions, such as @scheme[list], accept any number -of arguments. Some functions accept a range of argument counts; for -example @scheme[substring] accepts either two or three arguments. A -function's @idefterm{arity} is the number of arguments that it -accepts. +arguments. Some functions, such as @scheme[+] or @scheme[list], accept +any number of arguments. Some functions accept a range of argument +counts; for example @scheme[substring] accepts either two or three +arguments. A function's @idefterm{arity} is the number of arguments +that it accepts. @;------------------------------------------------------------------------ @section[#:tag "guide:keyword-args"]{Keyword Arguments} diff --git a/collects/scribblings/guide/binding.scrbl b/collects/scribblings/guide/binding.scrbl index 5a2b2ce158..c3595331fb 100644 --- a/collects/scribblings/guide/binding.scrbl +++ b/collects/scribblings/guide/binding.scrbl @@ -3,7 +3,7 @@ @require[(lib "eval.ss" "scribble")] @require["guide-utils.ss"] -@title{Identifiers and Binding} +@title[#:tag "guide:binding"]{Identifiers and Binding} The context of an expression determines the meaning of identifiers that appear in the expression. In particular, starting a module with @@ -12,7 +12,7 @@ the language @schememodname[big], as in @schememod[big] means that, within the module, the identifiers described in this guide -have the the meaning described here: @scheme[cons] refers to the +start with the meaning described here: @scheme[cons] refers to the function that creates a pair, @scheme[car] refers to the function that extracts the first element of a pair, and so on. @@ -21,7 +21,7 @@ that extracts the first element of a pair, and so on. Forms like @scheme[define], @scheme[lambda], and @scheme[let] associate a meaning with one or more identifiers; that is, they -@defterm{bind} identifier. The part of the program for which the +@defterm{bind} identifiers. The part of the program for which the binding applies is the @defterm{scope} of the binding. The set of bindings in effect for a given expression is the expression's @defterm{environment}. @@ -67,7 +67,7 @@ existing binding. Even identifiers like @scheme[define] and @scheme[lambda] get their meanings from bindings, though they have @defterm{transformer} -bindings (whcih means that they define syntactic forms) instead of +bindings (which means that they indicate syntactic forms) instead of value bindings. Since @scheme[define] has a transformer binding, the identifier @schemeidfont{define} cannot be used by itself to get a value. However, the normal binding for @schemeidfont{define} can be diff --git a/collects/scribblings/guide/cond.scrbl b/collects/scribblings/guide/cond.scrbl new file mode 100644 index 0000000000..b320c9d6b4 --- /dev/null +++ b/collects/scribblings/guide/cond.scrbl @@ -0,0 +1,163 @@ +#reader(lib "docreader.ss" "scribble") +@require[(lib "manual.ss" "scribble")] +@require[(lib "eval.ss" "scribble")] +@require["guide-utils.ss"] + +@title{Conditionals} + +Most functions used for branching, such as @scheme[<] and +@scheme[string?], produce either @scheme[#t] or @scheme[#f]. Scheme's +branching forms, however, treat any value other than @scheme[#f] as +true. We we say a @defterm{true value} to mean any value other than +@scheme[#f]. + +This convention for ``true value'' meshes well with protocols where +@scheme[#f] can serve as failure or to indicate that an optional value +is not supplied. (Beware of overusing this trick, and remember that an +exception is usually a better mechanism to report failure.) + +For example, the @scheme[member] function serves double duty; it can +be used to find the tail of a list that starts with a particular item, +or it can be used to simply check whether an item is present in a +list: + +@interaction[ +(member "Groucho" '("Harpo" "Zeppo")) +(member "Groucho" '("Harpo" "Groucho" "Zeppo")) +(if (member "Groucho" '("Harpo" "Zeppo")) + 'yep + 'nope) +(if (member "Groucho" '("Harpo" "Groucho" "Zeppo")) + 'yep + 'nope) +] + +@;------------------------------------------------------------------------ +@section{Simple Branching: @scheme[if]} + +In an @scheme[if] form, + +@specform[(if test-expr then-expr else-expr)] + +the @scheme[_test-expr] is always evaluated. If it produces any value +other than @scheme[#f], then @scheme[_then-expr] is +evaluated. Otherwise, @scheme[_else-expr] is evaluated. + +An @scheme[if] form must have both an @scheme[_then-expr] and an +@scheme[_else-expr]; the latter is not optional. To perform (or skip) +side-effects based on a @scheme[_test-expr], use @scheme[when] or +@scheme[unless], which we describe later in @secref["guide:begin"]. + +@;------------------------------------------------------------------------ +@section{Combining Tests: @scheme[and] and @scheme[or]} + +Scheme's @scheme[and] and @scheme[or] are syntactic forms, rather than +functions. Unlike a function, the @scheme[and] and @scheme[or] forms +can skip evaluation of later expressions if an earlier one determines +the answer. + +@specform[(and expr ...)] + +An @scheme[or] form produces @scheme[#f] if any of its @scheme[expr]s +produces @scheme[#f]. Otherwise, it produces the value of its last +@scheme[_expr]. As a special case, @scheme[(and)] produces +@scheme[#t]. + +@specform[(or expr ...)] + +The @scheme[and] form produces @scheme[#f] if any of its +@scheme[_expr]s produces @scheme[#f]. Otherwise, it produces the first +non-@scheme[#f] value from its @scheme[expr]s. As a special case, +@scheme[(or)] produces @scheme[#f]. + +@examples[ +(code:line + (define (got-milk? lst) + (and (not (null? lst)) + (or (eq? 'milk (car lst)) + (got-milk? (cdr lst))))) (code:comment #, @t{recurs only if needed})) +(got-milk? '(apple banana)) +(got-milk? '(apple milk banana)) +] + +If evaluation reaches the last @scheme[_expr] of an @scheme[and] or +@scheme[or] form, then the @scheme[_expr]'s value directly determines +the @scheme[and] or @scheme[or] result. Therefore, the last +@scheme[expr] is in tail position, which means that the above +@scheme[got-milk?] function runs in constant space. + +@margin-note{For an introduction to tail calls and tail positions, see +@secref["guide:tail-recursion"].} + +@;------------------------------------------------------------------------ +@section{Chaining Tests: @scheme[cond]} + +The @scheme[cond] form chains a series of tests to select a result +expression. To a first approximation, the syntax of @scheme[cond] is +as follows: + +@specform[(cond [test-expr expr ...+] + ...)] + +Each @scheme[_test-expr] is evaluated in order. If it produces +@scheme[#f], the corresponding @scheme[_expr]s are ignored, and +evaluation proceeds to the next @scheme[_test-expr]. As soon as a +@scheme[_test-expr] produces a true value, its @scheme[_text-expr]s +are evaluated to produce the result for the @scheme[cond] form, and no +further @scheme[_test-expr]s are evaluated. + +The last @scheme[_test-expr] in a @scheme[cond] can be replaced by +@scheme[else]. In terms of evaluation, @scheme[else] serves as a +synonym for @scheme[#t], but it clarifies that the last clause is +meant to catch all remaining cases. If @scheme[else] is not used, then +it is possible that no @scheme[_test-expr]s produce a true value; in +that case, the result of the @scheme[cond] expression is +@|void-const|. + +@examples[ +(cond + [(= 2 3) (error "wrong!")] + [(= 2 2) 'ok]) +(cond + [(= 2 3) (error "wrong!")]) +(cond + [(= 2 3) (error "wrong!")] + [else 'ok]) +] + +@def+int[ +(define (got-milk? lst) + (cond + [(null? lst) #f] + [(eq? 'milk (car lst)) #t] + [else (got-milk? (cdr lst))])) +(got-milk? '(apple banana)) +(got-milk? '(apple milk banana)) +] + +The full syntax of @scheme[cond] includes two more kinds of clauses: + +@specform/subs[#:literals (else =>) + (cond cond-clause ...) + ([cond-clause [test-expr then-expr ...+] + [else then-expr ...+] + [test-expr => proc-expr] + [test-expr]])] + +The @scheme[=>] variant captures the true result of its +@scheme[_test-expr] and passes it to the result of the +@scheme[_proc-expr], which must be a function of one argument. + +@examples[ +(define (after-groucho lst) + (cond + [(member "Groucho" lst) => cdr] + [else (error "not there")])) + +(after-groucho '("Harpo" "Groucho" "Zeppo")) +(after-groucho '("Harpo" "Zeppo")) +] + +A clause that includes only a @scheme[_test-expr] is rarely used. It +captures the true result of the @scheme[_test-expr], and simply +returns the result for the whole @scheme[cond] expression. diff --git a/collects/scribblings/guide/define.scrbl b/collects/scribblings/guide/define.scrbl index a50fb793b8..4dcfb03978 100644 --- a/collects/scribblings/guide/define.scrbl +++ b/collects/scribblings/guide/define.scrbl @@ -30,7 +30,7 @@ definitions: which is a shorthand for @schemeblock[ -(define id (lambda (arg ...) _body ...+)) +(define _id (lambda (_arg ...) _body ...+)) ] @defexamples[ @@ -51,12 +51,12 @@ The function shorthand via @scheme[define] also supports a ``rest'' argument (i.e., a final argument to collect extra arguments in a list): -@specform[(define (id arg ... . rest-id) expr)]{} +@specform[(define (id arg ... . rest-id) body ...+)]{} which is a shorthand @schemeblock[ -(define id (lambda (id arg ... . rest-id) body-expr ...+)) +(define _id (lambda (_arg ... . _rest-id) _body ...+)) ] @defexamples[ @@ -69,22 +69,25 @@ which is a shorthand @section{Curried Function Shorthand} Consider the following @scheme[make-add-suffix] function that takes a -string and returns another function that takes a string. Normally, the -result of @scheme[make-add-suffix] would be sent to some other -function, but it could be called directly, like this: +string and returns another function that takes a string: @def+int[ (define make-add-suffix (lambda (s2) (lambda (s) (string-append s s2)))) +] +Although it's not common, result of @scheme[make-add-suffix] could be +called directly, like this: + +@interaction[ ((make-add-suffix "!") "hello") ] -In a sense, the @scheme[make-add-suffix] function takes two arguments, -but it takes them one at a time. A function that takes some of its -arguments and returns a function to consume more is sometimes called a -@defterm{curried function}. +In a sense, @scheme[make-add-suffix] is a function takes two +arguments, but it takes them one at a time. A function that takes some +of its arguments and returns a function to consume more is sometimes +called a @defterm{curried function}. Using the function-shorthand form of @scheme[define], @scheme[make-add-suffix] can be written equivalently as @@ -236,7 +239,7 @@ the result is a special value @|undefined-const|. A sequence of internal definitions using just @scheme[define] is easily translated to an equivalent @scheme[letrec] form (as introduced in the next section). However, other definition forms can appear as a -@scheme[_body], including @scheme[define-struct] (see +@scheme[_body], including @scheme[define-values], @scheme[define-struct] (see @secref["guide:define-struct"]) or @scheme[define-syntax] (see @secref["guide:macros"]). diff --git a/collects/scribblings/guide/forms.scrbl b/collects/scribblings/guide/forms.scrbl index 823761eed0..f5ffa6f8ba 100644 --- a/collects/scribblings/guide/forms.scrbl +++ b/collects/scribblings/guide/forms.scrbl @@ -48,7 +48,7 @@ convention implicitly defines the meaning of many meta-variables: Square brackets in the grammar indicate a parenthesized sequence of forms, where square brackets are normally used (by convention). That -is square brackets @italic{do not} mean optional parts of the +is, square brackets @italic{do not} mean optional parts of the syntactic form. A @schememetafont{...} indicates zero or more repetitions of the @@ -56,7 +56,7 @@ preceding form, and @schememetafont{...+} indicates one or more repetitions of the preceding datum. Otherwise, non-italicized identifiers stand form themselves. -Based on the above grammar, then, here are a few legal uses of +Based on the above grammar, then, here are a few conforming uses of @schemekeywordfont{something}: @schemeblock[ @@ -65,9 +65,10 @@ Based on the above grammar, then, here are a few legal uses of (#,(schemekeywordfont "something") [x my-favorite-martian x] (+ 1 2) #f) ] -Some syntactic forms refer to meta-variables that are not implicitly -defined and not previously defined. Such meta-variables are defined -using a BNF-like format for alternatives: +Some syntactic-form specifications refer to meta-variables that are +not implicitly defined and not previously defined. Such meta-variables +are defined after the main form, using a BNF-like format for +alternatives: @specform/subs[(#,(schemekeywordfont "something-else") [thing ...+] an-expr ...) ([thing thing-id @@ -83,11 +84,9 @@ form, a @scheme[_thing] is either an identifier or a keyword. @include-section["lambda.scrbl"] @include-section["define.scrbl"] @include-section["let.scrbl"] -@include-section["named-let.scrbl"] +@include-section["cond.scrbl"] -@section{Conditionals: @scheme[if], @scheme[cond], @scheme[and], and @scheme[or]} - -@section{Sequencing: @scheme[begin], @scheme[begin0], @scheme[when], and @scheme[unless]} +@section[#:tag "guide:begin"]{Sequencing: @scheme[begin], @scheme[begin0], @scheme[when], and @scheme[unless]} @section{Assignment: @scheme[set!]} diff --git a/collects/scribblings/guide/guide.scrbl b/collects/scribblings/guide/guide.scrbl index c75e0eace6..d3806cb19b 100644 --- a/collects/scribblings/guide/guide.scrbl +++ b/collects/scribblings/guide/guide.scrbl @@ -99,6 +99,13 @@ using @idefterm{contracts}. @; ---------------------------------------------------------------------- @section[#:tag "performance"]{Performance} +Every definition or expression is compiled to an internal bytecode +format. Standard optimizations are applied when compiling the +bytecode. For example, in an environment where when @scheme[+] has its +usual binding, the expression @scheme[(let ([x 1][y (lambda () 4)]) (+ +1 (y)))] is compiled the same as the constant @scheme[5] due to +constant propagation, constant folding, and inlining optimizations. + @; ---------------------------------------------------------------------- @section[#:tag "ffi"]{Foreign-Function Interface@aux-elem{ (FFI)}} diff --git a/collects/scribblings/guide/lambda.scrbl b/collects/scribblings/guide/lambda.scrbl index a61a4d0b57..0773e471e9 100644 --- a/collects/scribblings/guide/lambda.scrbl +++ b/collects/scribblings/guide/lambda.scrbl @@ -5,7 +5,7 @@ @title[#:tag "guide:lambda"]{Functions@aux-elem{ (Procedures)}: @scheme[lambda]} -Such a @scheme[lambda] expression creates a function. In the simplest +A @scheme[lambda] expression creates a function. In the simplest case, a @scheme[lambda] expression has the form @specform[ @@ -180,11 +180,11 @@ specifies a keyword-based argument with a default value. The @scheme[lambda] form does not directly support the creation of a function that accepts ``rest'' keywords. To construct a -function that accepts any and all keyword arguments, use +function that accepts all keyword arguments, use @scheme[make-keyword-procedure]. The function supplied to -@scheme[make-keyword-procedure] receives keyword arguments through -parallel lists in the first two (by-position) arguments, and -then all by-position arguments from an application as the +@scheme[make-keyword-procedure] receives keyword arguments +through parallel lists in the first two (by-position) arguments, +and then all by-position arguments from an application as the remaining by-position arguments. @margin-note{For an introduction to @scheme[keyword-apply], see diff --git a/collects/scribblings/guide/let.scrbl b/collects/scribblings/guide/let.scrbl index 3d5f15350e..32f2bc3cde 100644 --- a/collects/scribblings/guide/let.scrbl +++ b/collects/scribblings/guide/let.scrbl @@ -3,5 +3,183 @@ @require[(lib "eval.ss" "scribble")] @require["guide-utils.ss"] -@title{Local Binding: @scheme[let], @scheme[let*], and @scheme[letrec]} +@interaction-eval[(require (lib "file.ss"))] +@title{Local Binding} + +Although internal @scheme[define]s can be used for local binding, +Scheme provides three forms that give the programmer more +control over bindings: @scheme[let], @scheme[let*], and +@scheme[letrec]. + +@;------------------------------------------------------------------------ +@section{Parallel Binding: @scheme[let]} + +A @scheme[let] form binds a set of identifiers, each to the result of +some expression, for use in the @scheme[let] body: + +@specform[(let ([id expr] ...) body ...+)]{} + +The @scheme[_id]s are bound ``in parallel.'' That is, no @scheme[_id] +is bound in the right-hand side @scheme[_expr] for any @scheme[_id], +but all are available in the @scheme[_body]. The @scheme[_id]s must be +different from each other. + +@examples[ +(let ([me "Bob"]) + me) +(let ([me "Bob"] + [myself "Robert"] + [I "Bobby"]) + (list me myself I)) +(let ([me "Bob"] + [me "Robert"]) + me) +] + +The fact that an @scheme[_id]'s @scheme[_expr] does not see its own +binding is often useful for wrappers that must refer back to the old +value: + +@interaction[ +(let ([+ (lambda (x y) + (if (string? x) + (string-append x y) + (+ x y)))]) (code:comment #, @t{use original @scheme[+]}) + (list (+ 1 2) + (+ "see" "saw"))) +] + +Occasionally, the parallel nature of @scheme[let] bindings is +convenient for swapping or rearranging a set of bindings: + +@interaction[ +(let ([me "Tarzan"] + [you "Jane"]) + (let ([me you] + [you me]) + (list me you))) +] + +The characterization of @scheme[let] bindings as ``parallel'' is not +meant to imply concurrent evaluation. The @scheme[_expr]s are +evaluated in order, even though the bindings are delayed until all +@scheme[_expr]s are evaluated. + +@;------------------------------------------------------------------------ +@section{Sequential Binding: @scheme[let*]} + +The syntax of @scheme[let*] is the same as @scheme[let]: + +@specform[(let* ([id expr] ...) body ...+)]{} + +The difference is that each @scheme[_id] is available for use in later +@scheme[_expr]s, as well as in the @scheme[_body]. Furthermore, the +@scheme[_id]s need not be distinct, and the most recent binding is the +visible one. + +@examples[ +(let* ([x (list "Borroughs")] + [y (cons "Rice" x)] + [z (cons "Edgar" y)]) + (list x y z)) +(let* ([name (list "Borroughs")] + [name (cons "Rice" name)] + [name (cons "Edgar" name)]) + name) +] + +In other words, a @scheme[let*] form is equivalent to nested +@scheme[let] forms, each with a single binding: + +@interaction[ +(let ([name (list "Borroughs")]) + (let ([name (cons "Rice" name)]) + (let ([name (cons "Edgar" name)]) + name))) +] + +@;------------------------------------------------------------------------ +@section{Recursive Binding: @scheme[letrec]} + +The syntax of @scheme[letrec] is also the same as @scheme[let]: + +@specform[(letrec ([id expr] ...) body ...+)]{} + +While @scheme[let] makes its bindings available only in the +@scheme[_body]s, and @scheme[let*] makes its bindings available to any +later binding @scheme[_expr], @scheme[letrec] makes its bindings +available to all other @scheme[_expr]s---even earlier ones. In other +words, @scheme[letrec] bindings are recursive. + +The @scheme[_expr]s in a @scheme[letrec] form are most often +@scheme[lambda] forms for recursive and mutually recursive functions: + +@interaction[ +(letrec ([swing + (lambda (t) + (if (eq? (car t) 'tarzan) + (cons 'vine + (cons 'tarzan (cddr t))) + (cons (car t) + (swing (cdr t)))))]) + (swing '(vine tarzan vine vine))) +] + +@interaction[ +(letrec ([tarzan-in-tree? + (lambda (name path) + (or (equal? name "tarzan") + (and (directory-exists? path) + (tarzan-in-directory? path))))] + [tarzan-in-directory? + (lambda (dir) + (ormap (lambda (elem) + (tarzan-in-tree? (path-element->string elem) + (build-path dir elem))) + (directory-list dir)))]) + (tarzan-in-tree? "tmp" (find-system-path 'temp-dir))) +] + +While the @scheme[_expr]s of a @scheme[letrec] form are typically +@scheme[lambda] expressions, they can be any expression. The +expressions are evaluated in order, and after each value is obtained, +it is immediately associated with its corresponding @scheme[_id]. If +an @scheme[_id] is referenced before its value is ready, the result is +@|undefined-const|, as just as for internal definitions. + +@interaction[ +(letrec ([quicksand quicksand]) + quicksand) +] + +@; ---------------------------------------- +@include-section["named-let.scrbl"] + +@; ---------------------------------------- +@section{Multiple Values: @scheme[let-values], @scheme[let*-values], and @scheme[letrec-values]} + +In the same way that @scheme[define-values] binds multiple +results in a definition (see @secref["guide:multiple-values"]), +@scheme[let-values], @scheme[let*-values], and +@scheme[letrec-values] bind multiple results locally. + +@specform[(let-values ([(id ...) expr] ...) + body ...+)] +@specform[(let*-values ([(id ...) expr] ...) + body ...+)] +@specform[(letrec-values ([(id ...) expr] ...) + body ...+)] + +Each @scheme[_expr] must produce as many values as coresponding +@scheme[_id]s. The binding rules are the same for the forms +without @schemekeywordfont{-values} forms: the @scheme[_id]s of +@scheme[let-values] are bound only in the @scheme[_body]s, the +@scheme[_id]s of @scheme[let*-values]s are bound in +@scheme[_expr]s of later clauses, and the @scheme[_id]s of +@scheme[letrec-value]s are bound for all @scheme[_expr]s. + +@examples[ +(let-values ([(q r) (quotient/remainder 14 3)]) + (list q r)) +] diff --git a/collects/scribblings/guide/lists.scrbl b/collects/scribblings/guide/lists.scrbl index 60f1dc5763..d117516b5d 100644 --- a/collects/scribblings/guide/lists.scrbl +++ b/collects/scribblings/guide/lists.scrbl @@ -182,6 +182,9 @@ If the derivation of the above definitions is mysterious to you, consider reading @|HtDP|. If you are merely suspicious of the use of recursive calls instead of a looping construct, then read on. +@;------------------------------------------------------------------------ +@section[#:tag "guide:tail-recursion"]{Tail Recursion} + Both the @scheme[my-length] and @scheme[my-map] functions run in @math{O(n)} time for a list of length @math{n}. This is easy to see by imagining how @scheme[(my-length (list "a" "b" "c"))] must evaluate: @@ -238,7 +241,10 @@ one, because that takes up space for no good reason. This evaluation behavior is sometimes called @idefterm{tail-call optimization}, but it's not merely an ``optimization'' in Scheme; it's -a guarantee about the way the code will run. +a guarantee about the way the code will run. More precisely, an +expression in @idefterm{tail position} with respect to another +expression does not take extra computation space over the other +expression. In the case of @scheme[my-map], @math{O(n)} space complexity is reasonable, since it has to generate a result of size diff --git a/collects/scribblings/guide/named-let.scrbl b/collects/scribblings/guide/named-let.scrbl index a6696979cb..d424026ca6 100644 --- a/collects/scribblings/guide/named-let.scrbl +++ b/collects/scribblings/guide/named-let.scrbl @@ -10,18 +10,16 @@ same syntactic keyword @scheme[let] as for local binding, but an identifier after the @scheme[let] (instead of an immediate open parenthesis) triggers a different parsing. -In general, - -@schemeblock[ +@specform[ (let _proc-id ([_arg-id _init-expr] ...) - _body-expr ...+) + _body ...+) ] -is equivalent to +A named @scheme[let] form is equivalent to @schemeblock[ (letrec ([_proc-id (lambda (_arg-id ...) - _body-expr ...+)]) + _body ...+)]) (_proc-id _init-expr ...)) ] diff --git a/collects/scribblings/guide/ports.scrbl b/collects/scribblings/guide/ports.scrbl new file mode 100644 index 0000000000..2b6451714e --- /dev/null +++ b/collects/scribblings/guide/ports.scrbl @@ -0,0 +1,31 @@ +#reader(lib "docreader.ss" "scribble") +@require[(lib "manual.ss" "scribble")] +@require[(lib "eval.ss" "scribble")] +@require["guide-utils.ss"] + +@title[#:tag "ports"]{Input and Output Ports} + +A @defterm{port} encapsulates an I/O stream, normally for just one +direction. An @defterm{input port} reads from a stream, and an +@defterm{output port} writes to a string. + +For many procedures that accept a port argument, the argument is +optional, and it defaults to either the @defterm{current input port} +or @defterm{current output port}. For @exec{mzscheme}, the current +ports are initialized to the process's stdin and stdout. The +@scheme[current-input-port] and @scheme[current-output-port] +procedures, whien called with no arguments, return the current output +and input port, respectively. + +@examples[ +(display "hello world\n") +(display "hello world\n" (current-output-port)) +] + +Ports are created by various procedures that specific to the different +kinds of streams. For example, @scheme[open-input-file] creates an +input port for reading from a file. Procedures like +@scheme[with-input-from-file] both create a port and install it as the +current port while calling a given body procedure. + +See @secref["io"] for information about using ports. diff --git a/collects/scribblings/reference/derived.scrbl b/collects/scribblings/reference/derived.scrbl index dbdcb01efc..d4f9f4b1eb 100644 --- a/collects/scribblings/reference/derived.scrbl +++ b/collects/scribblings/reference/derived.scrbl @@ -5,4 +5,143 @@ @local-table-of-contents[] + +@;------------------------------------------------------------------------ +@section[#:tag "mz:cond"]{Conditionals: @scheme[cond]} + +@defform/subs[#:literals (else =>) + (cond cond-clause ...) + ([cond-clause [test-expr then-expr ...+] + [else then-expr ...+] + [test-expr => proc-expr] + [test-expr]])]{ + +A @scheme[cond-clause] that starts with @scheme[else] must be the last +@scheme[cond-clause]. + +If no @scheme[cond-clause]s are present, the result is @|void-const|. + +If only a @scheme[[else then-expr ...+]] is present, then the +@scheme[then-expr]s are evaluated. The results from all but the last +@scheme[then-expr] are ignored. The results of the last +@scheme[then-expr], which is in tail position with respect to the +@scheme[cond] form, provides the result for the whole @scheme[cond] +form. + +Otherwise, the first @scheme[test-expr] is evaluated. If it produces +@scheme[#f], then the result is the same as a @scheme[cond] form with +the remaining @scheme[cond-clause]s, in tail position with respect to +the original @scheme[cond] form. Otherwise, evaluation depends on the +form of the @scheme[cond-clause]: + +@specsubform[[test-expr then-expr ...+]]{The @scheme[then-expr]s are +evaluated in order, and the results from all but the last +@scheme[then-expr] are ignored. The results of the last +@scheme[then-expr], which is in tail position with respect to the +@scheme[cond] form, provides the result for the whole @scheme[cond] +form.} + +@specsubform[#:literals (=>) [test-expr => proc-expr]]{The @scheme[proc-expr] is +evaluated, and it must produce a procedure that accepts on argument, +otherwise the @exnraise[exn:fail:contract]. The procedure is applied +to the result of @scheme[test-expr] in tail position with respect to +the @scheme[cond] expression.} + +@specsubform[[test-expr]]{The result of the @scheme[test-expr] is +returned as the result of the @scheme[cond] form. The +@scheme[test-expr] is not in tail position.} + +@examples[ +(cond) +(cond + [else 5]) +(cond + [(positive? -5) (error "doesn't get here")] + [(zero? -5) (error "doesn't get here, either")] + [(positive? 5) 'here]) +(cond + [(member 2 '(1 2 3)) => (lambda (l) (map - l))]) +(cond + [(member 2 '(1 2 3))]) +]} + +@;------------------------------------------------------------------------ +@section{Boolean Combination: @scheme[and] and @scheme[or]} + +@defform[(and expr ...)]{ + +If no @scheme[expr]s are provided, then result is @scheme[#f]. + +If a single @scheme[expr] is provided, then it is in tail position, so +the results of the @scheme[and] expression are the results of the +@scheme[expr]. + +Otherwise, the first @scheme[expr] is evaluated. If it produces +@scheme[#f], the result of the @scheme[and] expression is +@scheme[#f]. Otherwise, the result is the same as an @scheme[and] +expression with the remaining @scheme[expr]s in tail position with +respect to the original @scheme[and] form. + +@examples[ +(and) +(and 1) +(and (values 1 2)) +(and #f (error "doesn't get here")) +(and #t 5) +]} + +@defform[(or expr ...)]{ + +If no @scheme[expr]s are provided, then result is @scheme[#t]. + +If a single @scheme[expr] is provided, then it is in tail position, so +the results of the @scheme[and] expression are the results of the +@scheme[expr]. + +Otherwise, the first @scheme[expr] is evaluated. If it produces a +value other than @scheme[#f], that result is the result of the +@scheme[or] expression. Otherwise, the result is the same as an +@scheme[or] expression with the remaining @scheme[expr]s in tail +position with respect to the original @scheme[or] form. + +@examples[ +(or) +(or 1) +(or (values 1 2)) +(or 5 (error "doesn't get here")) +(or #f 5) +]} + + +@;------------------------------------------------------------------------ +@section{Guarded Evaluation: @scheme[when] and @scheme[unless]} + +@defform[(while test-expr expr ...)]{ + +Evaluates the @scheme[text-expr]. If the result is any value other +than @scheme[#f], the @scheme[expr]s are evaluated, and the results +are ignored. No @scheme[expr] is in tail position with respect to the +@scheme[when] form. + +@examples[ +(when (positive? -5) + (display "hi")) +(when (positive? 5) + (display "hi") + (display " there")) +]} + +@defform[(unless test-expr expr ...)]{ + +Equivalent to @scheme[(when (not test-expr) expr ...)]. + +@examples[ +(unless (positive? 5) + (display "hi")) +(unless (positive? -5) + (display "hi") + (display " there")) +]} + +@;------------------------------------------------------------------------ @include-section["for.scrbl"] diff --git a/collects/scribblings/reference/model.scrbl b/collects/scribblings/reference/model.scrbl index 0690eb8588..3493db7d16 100644 --- a/collects/scribblings/reference/model.scrbl +++ b/collects/scribblings/reference/model.scrbl @@ -69,7 +69,7 @@ application of @scheme[-] cannot be reduced until the sub-expression @scheme[(+ 1 1)] is reduced. Thus, the specification of each syntactic form specifies how (some of) -it's sub-expressions are evaluated, and then how the results are +its sub-expressions are evaluated, and then how the results are combined to reduce the form away. The @defterm{dynamic extent} of an expression is the sequence of @@ -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) (+ 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) 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, @scheme[(void)], 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 @@ -235,58 +235,58 @@ create objects, such as @scheme[vector], add to the set of objects: (define y x) (vector-set! x 0 11) (vector-ref y 0))] -[{(define #(10 20))} +[{(define (vector 10 20))} {} (begin (code:hilite (define x )) (define y x) (vector-set! x 0 11) (vector-ref y 0))] -[{(define #(10 20))} +[{(define (vector 10 20))} {(define x )} - (code:hilite (begin #,void-const + (code:hilite (begin (void) (define y x) (vector-set! x 0 11) (vector-ref y 0)))] -[{(define #(10 20))} +[{(define (vector 10 20))} {(define x )} (begin (define y (code:hilite x)) (vector-set! x 0 11) (vector-ref y 0))] -[{(define #(10 20))} +[{(define (vector 10 20))} {(define x )} (begin (code:hilite (define y )) (vector-set! x 0 11) (vector-ref y 0))] -[{(define #(10 20))} +[{(define (vector 10 20))} {(define x ) (define y )} - (code:hilite (begin #,void-const + (code:hilite (begin (void) (vector-set! x 0 11) (vector-ref y 0)))] -[{(define #(10 20))} +[{(define (vector 10 20))} {(define x ) (define y )} (begin (vector-set! (code:hilite x) 0 11) (vector-ref y 0))] -[{(define #(10 20))} +[{(define (vector 10 20))} {(define x ) (define y )} (begin (code:hilite (vector-set! 0 11)) (vector-ref y 0))] -[{(define #(11 20))} +[{(define (vector 11 20))} {(define x ) (define y )} - (code:hilite (begin #,void-const + (code:hilite (begin (void) (vector-ref y 0)))] -[{(define #(11 20))} +[{(define (vector 11 20))} {(define x ) (define y )} (vector-ref (code:hilite y) 0)] -[{(define #(11 20))} +[{(define (vector 11 20))} {(define x ) (define y )} (code:hilite (vector-ref 0))] -[{(define #(11 20))} +[{(define (vector 11 20))} {(define x ) (define y )} 11] @@ -334,8 +334,8 @@ specified with the datatype and its associated procedures. In the program state @prog-steps[ -[{(define #(10 20)) - (define #(0))} +[{(define (vector 10 20)) + (define (vector 0))} {(define x )} (+ 1 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) xloc))] [{(define (lambda (x) (begin (set! x 3) x)))} {(define f ) (define xloc 3)} @@ -463,7 +463,7 @@ in an initial program refer to variables. A top-level binding is both a variable and a location. Any other variable is always replaced by a location at run-time, so that evaluation of expressions involves only locations. A single non-top-level variable, such as a procedure -argument, can correspond to multiple locations at different times. +argument, can correspond to different locations at different times. The replacement of a variable with a location during evaluation implements Scheme's @defterm{lexical scoping}. For example, when the @@ -473,12 +473,14 @@ procedure, including with any nested @scheme[lambda] forms. As a result, future references of the variable always access the same location. +@guideintro["guide:binding"]{binding} + An @defterm{identifier} is source-program entity. Parsing a Scheme program reveals that some identifiers correspond to variables, some refer to syntactic forms, and some are quoted to produce a symbol or a -syntax object. An identifier @scheme[binds] another when the former is +syntax object. An identifier @defterm{binds} another when the former is parsed as a variable and the latter is parsed as a reference to the -former. An identifier is @scheme[bound] in a sub-expression if it +former. An identifier is @defterm{bound} in a sub-expression if it binds any uses of the identifier in the sub-expression that are not otherwise bound within the sub-expression; conversely, a binding for a sub-expression @defterm{shadows} any bindings in its context, so that diff --git a/collects/scribblings/reference/syntax.scrbl b/collects/scribblings/reference/syntax.scrbl index f359117ac7..ea7be9cc56 100644 --- a/collects/scribblings/reference/syntax.scrbl +++ b/collects/scribblings/reference/syntax.scrbl @@ -1,6 +1,8 @@ #reader(lib "docreader.ss" "scribble") @require["mz.ss"] +@define[cvt (schemefont "CVT")] + @title[#:tag "mz:syntax" #:style 'toc]{Core Syntactic Forms} This section describes core syntax forms that apear in a fully @@ -89,7 +91,7 @@ references are disallowed anywhere within a @scheme[module] form. @defform/none[(proc-expr arg ...)]{ -Applies a procedure, normally, when @scheme[proc-expr] is not an +Applies a procedure, when @scheme[proc-expr] is not an identifier that has a transformer binding (see @secref["mz:expansion"]). @@ -126,8 +128,8 @@ in the application, then the procedure is called with the values of the @scheme[arg-expr]s. Otherwise, the @exnraise[exn:fail:contract]. The continuation of the procedure call is the same as the continuation -of the application expression, so the result(s) of the application -expression is(are) the result(s) of the procedure. +of the application expression, so the results of the procedure are the +results of the application expression. The relative order of @scheme[_keyword]-based arguments matters only for the order of @scheme[_arg-expr] evaluations; the arguments are @@ -162,7 +164,7 @@ according to their order in the application form. Produces a procedure. The @scheme[gen-formals] determines the number of arguments that the procedure accepts. It is either a simple -@scheme[formals], or one of the extended forms. +@scheme[formals] or one of the extended forms. A simple @scheme[_formals] has one of the following three forms: @@ -239,12 +241,9 @@ When multiple identifiers appear in a @scheme[gen-formals], they must be distinct according to @scheme[bound-identifier=?]. If the procedure procedure by @scheme[lambda] is applied to fewer or -more arguments than it accepts, the @exnraise[exn:fail:contract]. If -@scheme[gen-formals] includes @scheme[keyword]s and an application -includes too few arguments before the keyword section, the same -keyword in multiple positions, or a keyword that is not among the -@scheme[gen-formals] @scheme[_keyword]s, then the -@exnraise[exn:fail:contract]. +more by-position or arguments than it accepts, to by-keyword arguments +that it does not accept, or without required by-keyword arguments, then +the @exnraise[exn:fail:contract]. The last @scheme[body] expression is in tail position with respect to the procedure body. @@ -322,9 +321,9 @@ within the @scheme[body]s to the procedure itself.} 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 -availablek. The @scheme[id]s are bound in the remaining @scheme[val-expr]s +available. The @scheme[id]s are bound in the remaining @scheme[val-expr]s as well as the @scheme[body]s, and the @scheme[id]s need not be -distinct. +distinct; later bindings shadow earlier bindings. @examples[ (let ([x 1] @@ -352,8 +351,9 @@ created first and filled with @|undefined-const|, and all @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]s. +values as corresponding @scheme[id]s, otherwise the +@exnraise[exn:fail:contract]. A separate location is created for each +@scheme[id], all of which are bound in the @scheme[body]s. @examples[ (let-values ([(x y) (quotient/remainder 10 3)]) @@ -392,8 +392,131 @@ and in the @scheme[body]s. ]} @;------------------------------------------------------------------------ -@section{Sequencing: @scheme[begin]} +@section[#:tag "mz:if"]{Conditionals: @scheme[if]} + +@defform[(if test-expr then-expr else-expr)]{ + +Evaluates @scheme[test-expr]. If it produces any value other than +@scheme[#f], then @scheme[then-expr] is evaluated, and its results are +the result for the @scheme[if] form. Otherwise, @scheme[else-expr] is +evaluated, and its results are the result for the @scheme[if] +form. The @scheme[then-expr] and @scheme[else-expr] are in tail +position with respect to the @scheme[if] form. + +@examples[ +(if (positive? -5) (error "doesn't get here") 2) +(if (positive? 5) 1 (error "doesn't get here")) +]} @;------------------------------------------------------------------------ @section[#:tag "mz:define"]{Definitions: @scheme[define] and @scheme[define-values]} +@defform*/subs[[(define id expr) + (define (head args) body ...+)] + ([head id + (head args)] + [args (code:line arg ...) + (code:line arg ... #, @schemeparenfont{.} rest-id)] + [arg arg-id + [arg-id default-expr] + (code:line keyword arg-id) + (code:line keyword [arg-id default-expr])])]{ + +The first form binds @scheme[id] to the result of @scheme[expr], and +the second form binds @scheme[id] to a procedure. In the second case, +the generation procedure is @scheme[(#,cvt (head args) body ...+)], +using the @|cvt| meta-function defined as follows: + +@schemeblock[ +(#,cvt (id . _gen-formals) . _datum) = (lambda _gen-formals . _datum) +(#,cvt (head . _gen-formals) . _datum) = (lambda _gen-formals expr) + #, @elem{if} (#,cvt head . _datum) = expr +] + +At the top level, the top-level binding @scheme[id] is created after +evaluating @scheme[expr], if it does not exist already, and the +top-level mapping of @scheme[id] (see @secref["mz:namespace"]) is set +to the binding at the same time. + +@defexamples[ +(define x 10) +x +] +@def+int[ +(define (f x) + (+ x 1)) +(f 10) +] + +@def+int[ +(define ((f x) [y 20]) + (+ x y)) +((f 10) 30) +((f 10)) +] +} + +@defform[(define-values (id ...) expr)]{ + +Evaluates the @scheme[expr], and binds the results to the +@scheme[id]s, in order, if the number of results matches the number of +@scheme[id]s; if @scheme[expr] produces a different number of results, +the @exnraise[exn:fail:contract]. + +At the top level, the top-level binding for each @scheme[id] is +created after evaluating @scheme[expr], if it does not exist already, +and the top-level mapping of each @scheme[id] (see +@secref["mz:namespace"]) is set to the binding at the same time. + +@defexamples[ +(define-values () (values)) +(define-values (x y z) (values 1 2 3)) +z +] +} + +@;------------------------------------------------------------------------ +@section{Sequencing: @scheme[begin] and @scheme[begin0]} + +@defform*[[(begin form ...) + (begin expr ...+)]]{ + +The first form applies when @scheme[begin] appears at the top level, +at module level, or in an internal-definition position (before any +expression in the internal-definition sequence). In that case, the +@scheme[begin] form is equivalent to splicing the @scheme[form]s into +the enclosing context. + +The second form applies for @scheme[begin] in an expression position. +In that case, the @scheme[expr]s are evaluated in order, and the +results are ignored for all but the last @scheme[expr]. The last +@scheme[expr] is in tail position with respect to the @scheme[begin] +form. + +@examples[ +(begin + (define x 10) + x) +(+ 1 (begin + (printf "hi\n") + 2)) +(let-values ([(x y) (begin + (values 1 2 3) + (values 1 2))]) + (list x y)) +]} + +@defform[(begin0 expr body ...+)]{ + +Evaluates the @scheme[expr], then evaluates the @scheme[body]s, +ignoring the @scheme[body] results. The results of the @scheme[expr] +are the results of the @scheme[begin0] form, but the @scheme[expr] is +in tail position only if no @scheme[body]s are present. + + + +@examples[ +(begin0 + (values 1 2) + (printf "hi\n")) +]} \ No newline at end of file