From 70ebf2d74797baff237cc7dabf99f4811c366868 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 19 Apr 2014 10:57:03 -0600 Subject: [PATCH] update docs on "undefined" --- .../scribblings/guide/void-and-undef.scrbl | 27 ++++++----- .../scribblings/reference/shared.scrbl | 46 +++++++++++++------ .../scribblings/reference/syntax.scrbl | 7 +-- 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/guide/void-and-undef.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/guide/void-and-undef.scrbl index 37c8930b0e..7e9a2dd1d8 100644 --- a/pkgs/racket-pkgs/racket-doc/scribblings/guide/void-and-undef.scrbl +++ b/pkgs/racket-pkgs/racket-doc/scribblings/guide/void-and-undef.scrbl @@ -1,5 +1,7 @@ #lang scribble/doc -@(require scribble/manual scribble/eval "guide-utils.rkt") +@(require scribble/manual scribble/eval "guide-utils.rkt" + (for-label racket/undefined + racket/shared)) @title[#:tag "void+undefined"]{Void and Undefined} @@ -21,21 +23,18 @@ directly to @|void-const|.) (list (void)) ] -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 -correspond to procedure arguments, @racket[let] bindings, or -@racket[let*] bindings; early reference requires a recursive binding -context, such as @racket[letrec] or local @racket[define]s in a -procedure body. Also, early references to top-level and module-level -bindings raise an exception, instead of producing -@|undefined-const|. For these reasons, @undefined-const rarely -appears. +The @racket[undefined] constant, which prints as @|undefined-const|, is +sometimes used as the result of a reference whose value is not yet +available. In previous versions of Racket (before version 6.1), +referencing a local binding too early produced @|undefined-const|; +too-early references now raise an exception, instead. + +@margin-note{The @racket[undefined] result can still be produced +in some cases by the @racket[shared] form.} @def+int[ -(define (strange) +(define (fails) (define x x) x) -(strange) +(fails) ] - diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/reference/shared.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/reference/shared.scrbl index c116eb0938..bb9bac5650 100644 --- a/pkgs/racket-pkgs/racket-doc/scribblings/reference/shared.scrbl +++ b/pkgs/racket-pkgs/racket-doc/scribblings/reference/shared.scrbl @@ -28,7 +28,7 @@ the last expression. The @racket[shared] form is similar to @racket[letrec], except that special forms of @racket[expr] are recognized (after partial macro expansion) to construct graph-structured data, where the corresponding -@racket[letrec] would instead produce @|undefined-const|s. +@racket[letrec] would instead produce a use-before-initialization error. Each @racket[expr] (after partial expansion) is matched against the following @racket[_shared-expr] grammar, where earlier variants in a @@ -46,7 +46,7 @@ production take precedence over later variants: (box-immutable in-immutable-expr) (mcons patchable-expr patchable-expr) (vector patchable-expr ...) - (box patchable-expr ...) + (box patchable-expr) (@#,|maker| patchable-expr ...)] [in-immutable-expr shell-id shell-expr @@ -76,26 +76,44 @@ for parsing precedence), the sub-expressions that were parsed via form is evaluated. Among such expressions, they are evaluated in the order as they appear within the @racket[shared] form. However, any reference to an @racket[id] bound by @racket[shared] produces -@|undefined-const|, even if the binding for the @racket[id] appears +a use-before-initialization errror, even if the binding for the @racket[id] appears before the corresponding @racket[_early-expr] within the @racket[shared] form. -The @racket[_shell-ids] and @racket[_shell-exprs] (not counting +The @racket[_shell-id]s and @racket[_shell-expr]s (not counting @racket[_patchable-expr] and @racket[_early-expr] sub-expressions) are -effectively evaluated next. A @racket[_shell-id] reference produces -the same value as the corresponding @racket[_id] will produce within -the @racket[body]s, assuming that @racket[_id] is never mutated with -@racket[set!]. This special handling of a @racket[_shell-id] -reference is one way in which @racket[shared] supports the creation of -cyclic data, including immutable cyclic data. +effectively evaluated next: + +@itemlist[ + + @item{A @racket[_shell-id] reference produces the same value as the + corresponding @racket[_id] will produce within the + @racket[body]s, assuming that @racket[_id] is never mutated + with @racket[set!]. This special handling of a + @racket[_shell-id] reference is one way in which + @racket[shared] supports the creation of cyclic data, including + immutable cyclic data.} + + @item{A @racket[_shell-expr] of the form @racket[(mcons + _patchable-expr _patchable-expr)], @racket[(vector _patchable-expr + ...)], @racket[(box _patchable-expr)], or @racket[(@#,|maker| + _patchable-expr ...)] produces a mutable value whose content + positions are initialized to @racket[undefined]. Each content + position is @deftech{patched} (i.e., updated) after the + corresponding @racket[_patchable-expr] expression is later + evaluated.} + +] Next, the @racket[_plain-expr]s are evaluated as for @racket[letrec], -where a reference to an @racket[id] produces @|undefined-const| if it +where a reference to an @racket[id] raises @racket[exn:fail:contract:variable] if it is evaluated before the right-hand side of the @racket[id] binding. -Finally, the @racket[_patchable-expr]s are evaluated. At this point, -all @racket[id]s are bound, so @racket[_patchable-expr]s also creates -data cycles (but only with cycles that can be created via mutation). +Finally, the @racket[_patchable-expr]s are evaluated and their values +replace @racket[undefined]s in the results of +@racket[_shell-expr]s. At this point, all @racket[id]s are bound, so +@racket[_patchable-expr]s can create data cycles (but only with cycles +that can be created via mutation). @examples[ #:eval shared-eval diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/reference/syntax.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/reference/syntax.scrbl index 1cd14ec155..17196db35f 100644 --- a/pkgs/racket-pkgs/racket-doc/scribblings/reference/syntax.scrbl +++ b/pkgs/racket-pkgs/racket-doc/scribblings/reference/syntax.scrbl @@ -1956,7 +1956,8 @@ corresponding @racket[val-expr] is evaluated. The @racket[id]s must be distinct @racket[bound-identifier=?]. Referencing or assigning to an @racket[id] before its initialization -raises @racket[exn:fail:contract:variable]. If an @racket[id] has an +raises @racket[exn:fail:contract:variable]. If an @racket[id] (i.e., +the binding instance or @racket[id]) has an @indexed-racket['undefined-error-name] @tech{syntax property} whose value is a symbol, the symbol is used as the name of the variable for error reporting, instead of the symbolic form of @racket[id]. @@ -2343,8 +2344,8 @@ defined as follows: @#,elem{if} (#,cvt head . _datum) = expr ] -In an @tech{internal-definition context} (see @secref["intdef-body"]), -a @racket[define] form introduces a local binding. +In an @tech{internal-definition context}, a @racket[define] form +introduces a local binding; see @secref["intdef-body"]. At the top level, the top-level binding for @racket[id] is created after evaluating @racket[expr], if it does not exist already, and the top-level mapping of @racket[id] (in the @techlink{namespace} linked