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
@(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)
]

View File

@ -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

View File

@ -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