update docs on "undefined"

This commit is contained in:
Matthew Flatt 2014-04-19 10:57:03 -06:00
parent 3fa9f99e2c
commit 70ebf2d747
3 changed files with 49 additions and 31 deletions

View File

@ -1,5 +1,7 @@
#lang scribble/doc #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} @title[#:tag "void+undefined"]{Void and Undefined}
@ -21,21 +23,18 @@ directly to @|void-const|.)
(list (void)) (list (void))
] ]
A constant that prints as @undefined-const is used as the result of a The @racket[undefined] constant, which prints as @|undefined-const|, is
reference to a local binding when the binding is not yet sometimes used as the result of a reference whose value is not yet
initialized. Such early references are not possible for bindings that available. In previous versions of Racket (before version 6.1),
correspond to procedure arguments, @racket[let] bindings, or referencing a local binding too early produced @|undefined-const|;
@racket[let*] bindings; early reference requires a recursive binding too-early references now raise an exception, instead.
context, such as @racket[letrec] or local @racket[define]s in a
procedure body. Also, early references to top-level and module-level @margin-note{The @racket[undefined] result can still be produced
bindings raise an exception, instead of producing in some cases by the @racket[shared] form.}
@|undefined-const|. For these reasons, @undefined-const rarely
appears.
@def+int[ @def+int[
(define (strange) (define (fails)
(define x x) (define x x)
x) x)
(strange) (fails)
] ]

View File

@ -28,7 +28,7 @@ the last expression.
The @racket[shared] form is similar to @racket[letrec], except that The @racket[shared] form is similar to @racket[letrec], except that
special forms of @racket[expr] are recognized (after partial macro special forms of @racket[expr] are recognized (after partial macro
expansion) to construct graph-structured data, where the corresponding 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 Each @racket[expr] (after partial expansion) is matched against the
following @racket[_shared-expr] grammar, where earlier variants in a 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) (box-immutable in-immutable-expr)
(mcons patchable-expr patchable-expr) (mcons patchable-expr patchable-expr)
(vector patchable-expr ...) (vector patchable-expr ...)
(box patchable-expr ...) (box patchable-expr)
(@#,|maker| patchable-expr ...)] (@#,|maker| patchable-expr ...)]
[in-immutable-expr shell-id [in-immutable-expr shell-id
shell-expr 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 form is evaluated. Among such expressions, they are evaluated in the
order as they appear within the @racket[shared] form. However, any order as they appear within the @racket[shared] form. However, any
reference to an @racket[id] bound by @racket[shared] produces 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 before the corresponding @racket[_early-expr] within the
@racket[shared] form. @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 @racket[_patchable-expr] and @racket[_early-expr] sub-expressions) are
effectively evaluated next. A @racket[_shell-id] reference produces effectively evaluated next:
the same value as the corresponding @racket[_id] will produce within
the @racket[body]s, assuming that @racket[_id] is never mutated with @itemlist[
@racket[set!]. This special handling of a @racket[_shell-id]
reference is one way in which @racket[shared] supports the creation of @item{A @racket[_shell-id] reference produces the same value as the
cyclic data, including immutable cyclic data. 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], 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. is evaluated before the right-hand side of the @racket[id] binding.
Finally, the @racket[_patchable-expr]s are evaluated. At this point, Finally, the @racket[_patchable-expr]s are evaluated and their values
all @racket[id]s are bound, so @racket[_patchable-expr]s also creates replace @racket[undefined]s in the results of
data cycles (but only with cycles that can be created via mutation). @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[ @examples[
#:eval shared-eval #:eval shared-eval

View File

@ -1956,7 +1956,8 @@ corresponding @racket[val-expr] is evaluated. The @racket[id]s must be distinct
@racket[bound-identifier=?]. @racket[bound-identifier=?].
Referencing or assigning to an @racket[id] before its initialization 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 @indexed-racket['undefined-error-name] @tech{syntax property} whose
value is a symbol, the symbol is used as the name of the variable for 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]. error reporting, instead of the symbolic form of @racket[id].
@ -2343,8 +2344,8 @@ defined as follows:
@#,elem{if} (#,cvt head . _datum) = expr @#,elem{if} (#,cvt head . _datum) = expr
] ]
In an @tech{internal-definition context} (see @secref["intdef-body"]), In an @tech{internal-definition context}, a @racket[define] form
a @racket[define] form introduces a local binding. introduces a local binding; see @secref["intdef-body"].
At the top level, the top-level binding for @racket[id] is created after 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 evaluating @racket[expr], if it does not exist already, and the
top-level mapping of @racket[id] (in the @techlink{namespace} linked top-level mapping of @racket[id] (in the @techlink{namespace} linked