Doc improvements to eval-model.scrbl

This commit is contained in:
Paul C. Anagnostopoulos 2018-10-19 12:10:08 -04:00 committed by Matthew Flatt
parent 23f6d2b43f
commit 9372ca1e3d

View File

@ -1,4 +1,5 @@
#lang scribble/doc #lang scribble/manual
@(require scribble/struct scribble/racket "mz.rkt" "prog-steps.rkt" @(require scribble/struct scribble/racket "mz.rkt" "prog-steps.rkt"
(for-syntax racket/base)) (for-syntax racket/base))
@ -10,7 +11,6 @@
@(define-syntax redex @(define-syntax redex
(syntax-rules () [(_ a) (*redex (racket a))])) (syntax-rules () [(_ a) (*redex (racket a))]))
@(define hole (make-element #f (list "[]"))) @(define hole (make-element #f (list "[]")))
@(define (*sub c e) (make-element #f (list c "[" e "]"))) @(define (*sub c e) (make-element #f (list c "[" e "]")))
@(define-syntax sub @(define-syntax sub
@ -44,11 +44,10 @@ Racket evaluation simplifies
(+ 1 1) @#,reduces 2 (+ 1 1) @#,reduces 2
] ]
The arrow @reduces above replaces the more traditional @tt{=} to The arrow @reduces replaces the more traditional @tt{=} to
emphasize that evaluation proceeds in a particular direction towards emphasize that evaluation proceeds in a particular direction toward
simpler expressions. In particular, a @deftech{value} is an simpler expressions. In particular, a @deftech{value}, such as the number @racket[2],
expression that evaluation simplifies no further, such as the number is an expression that evaluation simplifies no further.
@racket[2].
@;------------------------------------------------------------------------ @;------------------------------------------------------------------------
@section[#:tag "cont-model"]{Sub-expression Evaluation and Continuations} @section[#:tag "cont-model"]{Sub-expression Evaluation and Continuations}
@ -60,25 +59,26 @@ Some simplifications require more than one step. For example:
] ]
An expression that is not a @tech{value} can always be partitioned An expression that is not a @tech{value} can always be partitioned
into two parts: a @deftech{redex}, which is the part that changed in a into two parts: a @deftech{redex} (``reducible expression''),
which is the part that can change in a
single-step simplification (highlighted), and the single-step simplification (highlighted), and the
@deftech{continuation}, which is the evaluation @deftech{continuation}, which is the evaluation
context surrounding an expression. In @racket[(- 4 (+ 1 1))], the redex is @racket[(+ 1 1)], and context surrounding the redex. In @racket[(- 4 (+ 1 1))], the redex is @racket[(+ 1 1)], and
the continuation is @racket[(- 4 @#,hole)], where @hole takes the the continuation is @racket[(- 4 @#,hole)], where @hole indicates the
place of the redex. That is, the continuation says how to ``continue'' position of the redex. That is, the continuation says how to ``continue''
after the @tech{redex} is reduced to a @tech{value}. after the @tech{redex} is reduced to a @tech{value}.
Before some things can be evaluated, some sub-expressions must be Before some expressions can be evaluated, their sub-expressions must be
evaluated; for example, in the application @racket[(- 4 (+ 1 1))], the evaluated. For example, in the application @racket[(- 4 (+ 1 1))], the
application of @racket[-] cannot be reduced until the sub-expression application of @racket[-] cannot be reduced until the sub-expression
@racket[(+ 1 1)] is reduced. @racket[(+ 1 1)] is reduced.
Thus, the specification of each syntactic form specifies how (some of) Thus, the specification of each syntactic form specifies how (some of)
its 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. combined to reduce the form away.
The @deftech{dynamic extent} of an expression is the sequence of The @deftech{dynamic extent} of an expression is the sequence of
evaluation steps during which the expression contains the @tech{redex}. evaluation steps starting when the expression is selected as a @tech{redex}
and continuing until it is fully evaluated.
@;------------------------------------------------------------------------ @;------------------------------------------------------------------------
@section{Tail Position} @section{Tail Position}
@ -86,12 +86,12 @@ evaluation steps during which the expression contains the @tech{redex}.
An expression @racket[_expr1] is in @deftech{tail position} with An expression @racket[_expr1] is in @deftech{tail position} with
respect to an enclosing expression @racket[_expr2] if, whenever respect to an enclosing expression @racket[_expr2] if, whenever
@racket[_expr1] becomes a redex, its @tech{continuation} is the same @racket[_expr1] becomes a redex, its @tech{continuation} is the same
as was the enclosing @racket[_expr2]'s @tech{continuation}. as the enclosing @racket[_expr2]'s @tech{continuation}.
For example, the @racket[(+ 1 1)] expression is @italic{not} in @tech{tail For example, the @racket[(+ 1 1)] expression is @italic{not} in @tech{tail
position} with respect to @racket[(- 4 (+ 1 1))]. To illustrate, we use position} with respect to @racket[(- 4 (+ 1 1))]. To illustrate, we use
the notation @sub[_C _expr] to mean the expression that is produced by the notation @sub[_C _expr] to mean the expression that is produced by
substituting @racket[_expr] in place of @hole in the @tech{continuation} substituting @racket[_expr] in place of @hole in some arbitrary @tech{continuation}
@racket[_C]: @racket[_C]:
@racketblock[ @racketblock[
@ -99,16 +99,17 @@ substituting @racket[_expr] in place of @hole in the @tech{continuation}
] ]
In this case, the @tech{continuation} for reducing @racket[(+ 1 1)] is In this case, the @tech{continuation} for reducing @racket[(+ 1 1)] is
@sub[_C (- 4 @#,hole)], not just @racket[_C]. @sub[_C (- 4 @#,hole)], not just @racket[_C]. The requirement specified in the first paragraph above is not met.
In contrast, @racket[(+ 1 1)] is in @tech{tail position} with respect In contrast, @racket[(+ 1 1)] is in @tech{tail position} with respect
to @racket[(if (zero? 0) (+ 1 1) 3)], because, for any continuation to @racket[(if (zero? 0) (+ 1 1) 3)] because, for any continuation
@racket[_C], @racket[_C],
@racketblock[ @racketblock[
@#,sub[_C (if (zero? 0) (+ 1 1) 3)] @#,reduces @#,sub[_C (if #t (+ 1 1) 3)] @#,reduces @#,sub[_C (+ 1 1)] @#,sub[_C (if (zero? 0) (+ 1 1) 3)] @#,reduces @#,sub[_C (if #t (+ 1 1) 3)] @#,reduces @#,sub[_C (+ 1 1)]
] ]
The requirement specified in the first paragraph is met.
The steps in this reduction sequence are driven by the definition of The steps in this reduction sequence are driven by the definition of
@racket[if], and they do not depend on the @tech{continuation} @racket[if], and they do not depend on the @tech{continuation}
@racket[_C]. The ``then'' branch of an @racket[if] form is always in @racket[_C]. The ``then'' branch of an @racket[if] form is always in
@ -118,18 +119,19 @@ branch of an @racket[if] form is also in @tech{tail position}.
@tech{Tail-position} specifications provide a guarantee about the @tech{Tail-position} specifications provide a guarantee about the
asymptotic space consumption of a computation. In general, the asymptotic space consumption of a computation. In general, the
specification of @tech{tail positions} goes with each syntactic form, specification of @tech{tail positions} accompanies the description of
like @racket[if]. each syntactic form, such as @racket[if].
@;------------------------------------------------------------------------ @;------------------------------------------------------------------------
@section[#:tag "values-model"]{Multiple Return Values} @section[#:tag "values-model"]{Multiple Return Values}
A Racket expression can evaluate to @deftech{multiple values}, in the A Racket expression can evaluate to @deftech{multiple values}, similar
same way that a procedure can accept multiple arguments. to the way that a procedure can accept multiple arguments.
Most @tech{continuations} expect a particular number of result Most @tech{continuations} expect a certain number of result
@tech{values}. Indeed, most @tech{continuations}, such as @racket[(+ @tech{values}, although some @tech{continuations} can accept
@#,hole 1)] expect a single @tech{value}. The @tech{continuation} an arbitrary number. Indeed, most @tech{continuations}, such as @racket[(+
@#,hole 1)], expect a single @tech{value}. The @tech{continuation}
@racket[(let-values ([(x y) @#,hole]) _expr)] expects two result @racket[(let-values ([(x y) @#,hole]) _expr)] expects two result
@tech{values}; the first result replaces @racket[x] in the body @tech{values}; the first result replaces @racket[x] in the body
@racket[_expr], and the second replaces @racket[y] in @racket[_expr], and the second replaces @racket[y] in
@ -139,7 +141,7 @@ the result(s).
In general, the specification of a syntactic form indicates the In general, the specification of a syntactic form indicates the
number of @tech{values} that it produces and the number that it number of @tech{values} that it produces and the number that it
expects from each of its sub-expression. In addition, some procedures expects from each of its sub-expressions. In addition, some procedures
(notably @racket[values]) produce multiple @tech{values}, and some (notably @racket[values]) produce multiple @tech{values}, and some
procedures (notably @racket[call-with-values]) create continuations procedures (notably @racket[call-with-values]) create continuations
internally that accept a certain number of @tech{values}. internally that accept a certain number of @tech{values}.
@ -155,8 +157,8 @@ then an algebra student simplifies @tt{x + 1} as follows:
@verbatim{ x + 1 = 10 + 1 = 11} @verbatim{ x + 1 = 10 + 1 = 11}
Racket works much the same way, in that a set of @tech{top-level Racket works much the same way, in that a set of @deftech{top-level
variables} are available for substitutions on demand during variables} (see also @secref["vars-and-locs"]) are available for substitutions on demand during
evaluation. For example, given evaluation. For example, given
@racketblock[ @racketblock[
@ -169,15 +171,16 @@ then
#,(redex (+ x 1)) #,reduces #,(redex (+ 10 1)) #,reduces 11 #,(redex (+ x 1)) #,reduces #,(redex (+ 10 1)) #,reduces 11
] ]
In Racket, the way definitions appear is just as important as the way In Racket, the way definitions are created is just as important as the way
that they are used. Racket evaluation thus keeps track of both they are used. Racket evaluation thus keeps track of both
definitions and the current expression, and it extends the set of definitions and the current expression, and it extends the set of
definitions in response to evaluating forms such as @racket[define]. definitions in response to evaluating forms such as @racket[define].
Each evaluation step, then, takes the current set of definitions and Each evaluation step, then, transforms the current set of definitions and
program to a new set of definitions and program. Before a program into a new set of definitions and program. Before a
@racket[define] can be moved into the set of definitions, its @racket[define] can be moved into the set of definitions, its
right-hand expression must be reduced to a @tech{value}. second expression must be reduced to a @tech{value}.
(The first expression is used without evaluation.)
@prog-steps/no-obj[ @prog-steps/no-obj[
[{} [{}
@ -216,17 +219,18 @@ variables}, various procedures enable the modification of elements
within a compound data structure. For example, @racket[vector-set!] within a compound data structure. For example, @racket[vector-set!]
modifies the content of a vector. modifies the content of a vector.
To allow such modifications to data, we must distinguish between To explain such modifications to data, we must distinguish between
@tech{values}, which are the results of expressions, and @tech{values}, which are the results of expressions, and
@deftech{objects}, which hold the data referenced by a value. @deftech{objects}, which hold the data referenced by a value.
A few kinds of @tech{objects} can serve directly as values, including A few kinds of @tech{objects} can serve directly as values, including
booleans, @racket[(void)], and small exact integers. More generally, booleans, @racket[(void)], and small exact integers. More generally,
however, a @tech{value} is a reference to an @tech{object}. For however, a @tech{value} is a reference to an @tech{object} stored somewhere
example, a @tech{value} can be a reference to a particular vector that else. For example, a @tech{value} can refer to a particular vector that
currently holds the value @racket[10] in its first slot. If an currently holds the value @racket[10] in its first slot. If an
@tech{object} is modified, then the modification is visible through @tech{object} is modified via one @tech{value},
all copies of the @tech{value} that reference the same @tech{object}. then the modification is visible through
all copies of the @tech{value} that reference the @tech{object}.
In the evaluation model, a set of @tech{objects} must be carried along In the evaluation model, a set of @tech{objects} must be carried along
with each step in evaluation, just like the definition set. Operations with each step in evaluation, just like the definition set. Operations
@ -299,14 +303,15 @@ that create @tech{objects}, such as @racket[vector], add to the set of
The distinction between a @tech{top-level variable} and an object The distinction between a @tech{top-level variable} and an object
reference is crucial. A @tech{top-level variable} is not a reference is crucial. A @tech{top-level variable} is not a
@tech{value}; each time a @tech{variable} expression is evaluated, the @tech{value}, so it must be evaluated. Each time
value is extracted from the current set of definitions. An object a @tech{variable} expression is evaluated, the
reference, in contrast is a value, and therefore needs no further value of the variable is extracted from the current set of definitions. An object
evaluation. The model evaluation steps above use angle-bracketed reference, in contrast, is a value and therefore needs no further
evaluation. The evaluation steps above use angle-bracketed
@racket[<o1>] for an object reference to distinguish it from a @racket[<o1>] for an object reference to distinguish it from a
@tech{variable} name. @tech{variable} name.
A direct object reference can never appear in a text-based source An object reference can never appear directly in a text-based source
program. A program representation created with program. A program representation created with
@racket[datum->syntax], however, can embed direct references to @racket[datum->syntax], however, can embed direct references to
existing @tech{objects}. existing @tech{objects}.
@ -319,7 +324,7 @@ The @racket[eq?] operator compares two @tech{values}, returning
of equality is suitable for comparing objects that support imperative of equality is suitable for comparing objects that support imperative
update (e.g., to determine that the effect of modifying an object update (e.g., to determine that the effect of modifying an object
through one reference is visible through another reference). Also, an through one reference is visible through another reference). Also, an
@racket[eq?] test evaluates quickly, and @racket[eq?]-based hashing @racket[eq?] test evaluates quickly, and @racket[eq?]-based hashing
is more lightweight than @racket[equal?]-based hashing in hash tables. is more lightweight than @racket[equal?]-based hashing in hash tables.
In some cases, however, @racket[eq?] is unsuitable as a comparison In some cases, however, @racket[eq?] is unsuitable as a comparison
@ -351,14 +356,15 @@ In the program state
evaluation cannot depend on @racket[<o2>], because it is not part of evaluation cannot depend on @racket[<o2>], because it is not part of
the program to evaluate, and it is not referenced by any definition the program to evaluate, and it is not referenced by any definition
that is accessible in the program. The @tech{object} @racket[<o2>] may that is accessible by the program. The object is said to be
therefore be removed from the evaluation by @deftech{garbage not @deftech{reachable}. The @tech{object} @racket[<o2>] may
therefore be removed from the program state by @deftech{garbage
collection}. collection}.
A few special compound datatypes hold @deftech{weak references} to A few special compound datatypes hold @deftech{weak references} to
objects. Such weak references are treated specially by the garbage objects. Such weak references are treated specially by the garbage
collector in determining which @tech{objects} are reachable for the collector in determining which @tech{objects} are reachable for the
remainder of the computation. If an @tech{object} is reachable only remainder of the computation. If an @tech{object} is reachable @italic{only}
via a @tech{weak reference}, then the object can be reclaimed, and the via a @tech{weak reference}, then the object can be reclaimed, and the
@tech{weak reference} is replaced by a different @tech{value} @tech{weak reference} is replaced by a different @tech{value}
(typically @racket[#f]). (typically @racket[#f]).
@ -380,12 +386,12 @@ Given
@verbatim{ f(x) = x + 10} @verbatim{ f(x) = x + 10}
then an algebra student simplifies @tt{f(7)} as follows: an algebra student simplifies @tt{f(7)} as follows:
@verbatim{ f(7) = 7 + 10 = 17} @verbatim{ f(7) = 7 + 10 = 17}
The key step in this simplification is take the body of the defined The key step in this simplification is take the body of the defined
function @tt{f}, and then replace each @tt{x} with the actual function @tt{f} and replace each @tt{x} with the actual
@tech{value} @tt{7}. @tech{value} @tt{7}.
Racket procedure application works much the same way. A procedure is Racket procedure application works much the same way. A procedure is
@ -402,11 +408,12 @@ an @tech{object}, so evaluating @racket[(f 7)] starts with a
] ]
Unlike in algebra, however, the @tech{value} associated with an Unlike in algebra, however, the @tech{value} associated with an
argument can be changed in the body of a procedure by using argument parameter variable (not to be confused with parameters;
see @secref["parameter-model"]) can be changed in the body of a procedure by using
@racket[set!], as in the example @racket[(lambda (x) (begin (set! x 3) @racket[set!], as in the example @racket[(lambda (x) (begin (set! x 3)
x))]. Since the @tech{value} associated with @racket[x] can be x))]. Since the @tech{value} associated with parameter variable @racket[x] can be
changed, an actual value cannot be substituted for @racket[x] when changed, an argument value cannot be substituted for @racket[x] when
the procedure is applied. the procedure is first applied.
Instead, a new @deftech{location} is created for each @tech{variable} Instead, a new @deftech{location} is created for each @tech{variable}
on each application. The argument @tech{value} is placed in the on each application. The argument @tech{value} is placed in the
@ -437,7 +444,8 @@ not been used before and that cannot be generated again or
accessed directly. accessed directly.
Generating a @tech{location} in this way means that @racket[set!] Generating a @tech{location} in this way means that @racket[set!]
evaluates for @tech{local variables} in the same way as for evaluates for @tech{local variables}, including argument
parameter variables, in the same way as for
@tech{top-level variables}, because the @tech{local variable} is @tech{top-level variables}, because the @tech{local variable} is
always replaced with a @tech{location} by the time the @racket[set!] always replaced with a @tech{location} by the time the @racket[set!]
form is evaluated: form is evaluated:
@ -467,7 +475,7 @@ form is evaluated:
3] 3]
] ]
The substitution and @tech{location}-generation step of procedure The @tech{location}-generation and substitution step of procedure
application requires that the argument is a @tech{value}. Therefore, application requires that the argument is a @tech{value}. Therefore,
in @racket[((lambda (x) (+ x 10)) (+ 1 2))], the @racket[(+ 1 2)] in @racket[((lambda (x) (+ x 10)) (+ 1 2))], the @racket[(+ 1 2)]
sub-expression must be simplified to the @tech{value} @racket[3], and sub-expression must be simplified to the @tech{value} @racket[3], and
@ -481,17 +489,17 @@ Evaluation of a local-variable form, such as @racket[(let ([x (+ 1
that replaces every instance of @racket[x] in @racket[_expr]. that replaces every instance of @racket[x] in @racket[_expr].
@;------------------------------------------------------------------------ @;------------------------------------------------------------------------
@section{Variables and Locations} @section[#:tag "vars-and-locs"]{Variables and Locations}
A @deftech{variable} is a placeholder for a @tech{value}, and A @deftech{variable} is a placeholder for a @tech{value}, and
expressions in an initial program refer to @tech{variables}. A expressions in an initial program refer to @tech{variables}. A
@deftech{top-level variable} is both a @tech{variable} and a @tech{top-level variable} is both a @tech{variable} and a
@tech{location}. Any other @tech{variable} is always replaced by a @tech{location}. Any other @tech{variable} is always replaced by a
@tech{location} at run-time, so that evaluation of expressions @tech{location} at run-time; thus, evaluation of expressions
involves only @tech{locations}. A single @deftech{local variable} involves only @tech{locations}. A single @deftech{local variable}
(i.e., a non-top-level, non-module-level @tech{variable}), such as a (i.e., a non-top-level, non-module-level @tech{variable}), such as an
procedure argument, can correspond to different @tech{locations} argument parameter variable, can correspond to different @tech{locations}
through different instantiations. through different applications.
For example, in the program For example, in the program
@ -506,10 +514,10 @@ hold the value @racket[11].
The replacement of a @tech{variable} with a @tech{location} during The replacement of a @tech{variable} with a @tech{location} during
evaluation implements Racket's @deftech{lexical scoping}. For example, evaluation implements Racket's @deftech{lexical scoping}. For example,
when a procedure-argument @tech{variable} @racket[x] is replaced by when an argument parameter variable @racket[x] is replaced by
the @tech{location} @racket[xloc], then it is replaced throughout the the @tech{location} @racket[xloc], it is replaced @italic{throughout} the
body of the procedure, including any nested @racket[lambda] body of the procedure, including any nested @racket[lambda]
forms. As a result, future references of the @tech{variable} always forms. As a result, future references to the @tech{variable} always
access the same @tech{location}. access the same @tech{location}.
@;------------------------------------------------------------------------ @;------------------------------------------------------------------------