simplified world terminology
svn: r13041
This commit is contained in:
parent
78ec585827
commit
2821275df7
|
@ -32,9 +32,9 @@
|
|||
|
||||
This @tt{universe.ss} teachpack implements and provides the functionality
|
||||
for creating interactive, graphical programs that consist of plain
|
||||
mathematical functions. We refer to such programs as @defterm{world}
|
||||
mathematical functions. We refer to such programs as @deftech{world}
|
||||
programs. In addition, world programs can also become a part of a
|
||||
@defterm{universe}, a collection of worlds that can exchange messages.
|
||||
@deftech{universe}, a collection of worlds that can exchange messages.
|
||||
|
||||
The purpose of this documentation is to give experienced Schemers and HtDP
|
||||
teachers a concise overview for using the library. The first part of the
|
||||
|
@ -42,7 +42,7 @@ The purpose of this documentation is to give experienced Schemers and HtDP
|
|||
presents an illustration of how to design such programs for a simple
|
||||
domain; it is suited for a novice who knows how to design conditional
|
||||
functions for symbols. The second half of the documentation focuses on
|
||||
@tech{universe} programs: how it is managed via a server, how @tech{world}
|
||||
"universe" programs: how it is managed via a server, how @tech{world}
|
||||
programs register with the server, etc. The last two sections show how to
|
||||
design a simple universe of two communicating worlds.
|
||||
|
||||
|
@ -138,17 +138,17 @@ The following picture provides an intuitive overview of the workings of a
|
|||
|
||||
@image["nuworld.png"]
|
||||
|
||||
The @scheme[big-bang] form installs @scheme[World_0] as the initial
|
||||
world. The handlers @scheme[tock], @scheme[react], and @scheme[click] transform
|
||||
The @scheme[big-bang] form installs @scheme[World_0] as the initial @tech{WorldState}.
|
||||
The handlers @scheme[tock], @scheme[react], and @scheme[click] transform
|
||||
one world into another one; each time an event is handled, @scheme[done] is
|
||||
used to check whether the world is final, in which case the program is
|
||||
shut down; and finally, @scheme[draw] renders each world as a scene, which
|
||||
is then displayed on an external canvas.
|
||||
|
||||
@deftech{World} : @scheme[any/c]
|
||||
@deftech{WorldState} : @scheme[any/c]
|
||||
|
||||
The design of a world program demands that you come up with a data
|
||||
definition of all possible states. We use @tech{World} to refer to
|
||||
definition of all possible states. We use @tech{WorldState} to refer to
|
||||
this collection of data, using a capital W to distinguish it from the
|
||||
program. In principle, there are no constraints on this data
|
||||
definition though it mustn't be an instance of the @tech{Package}
|
||||
|
@ -176,7 +176,7 @@ The design of a world program demands that you come up with a data
|
|||
|
||||
starts a @tech{world} program in the initial state specified with
|
||||
@scheme[state-expr], which must of course evaluate to an element of
|
||||
@tech{World}. Its behavior is specified via the handler functions
|
||||
@tech{WorldState}. Its behavior is specified via the handler functions
|
||||
designated in the optional @scheme[spec] clauses, especially how the
|
||||
@tech{world} program deals with clock ticks, with key events, with mouse
|
||||
events, and eventually with messages from the universe; how it renders
|
||||
|
@ -190,7 +190,7 @@ The design of a world program demands that you come up with a data
|
|||
@item{
|
||||
@defform[(on-tick tick-expr)
|
||||
#:contracts
|
||||
([tick-expr (-> (unsyntax @tech{World}) (unsyntax @tech{World}))])]{
|
||||
([tick-expr (-> (unsyntax @tech{WorldState}) (unsyntax @tech{WorldState}))])]{
|
||||
|
||||
tell DrScheme to call the @scheme[tick-expr] function on the current
|
||||
world every time the clock ticks. The result of the call becomes the
|
||||
|
@ -199,7 +199,7 @@ current world. The clock ticks at the rate of 28 times per second.}}
|
|||
@item{
|
||||
@defform/none[(on-tick tick-expr rate-expr)
|
||||
#:contracts
|
||||
([tick-expr (-> (unsyntax @tech{World}) (unsyntax @tech{World}))]
|
||||
([tick-expr (-> (unsyntax @tech{WorldState}) (unsyntax @tech{WorldState}))]
|
||||
[rate-expr natural-number/c])]{
|
||||
tell DrScheme to call the @scheme[tick-expr] function on the current
|
||||
world every time the clock ticks. The result of the call becomes the
|
||||
|
@ -234,7 +234,7 @@ A character is used to signal that the user has hit an alphanumeric
|
|||
|
||||
@defform[(on-key change-expr)
|
||||
#:contracts
|
||||
([change-expr (-> (unsyntax @tech{World}) key-event? (unsyntax @tech{World}))])]{
|
||||
([change-expr (-> (unsyntax @tech{WorldState}) key-event? (unsyntax @tech{WorldState}))])]{
|
||||
tell DrScheme to call @scheme[change-expr] function on the current world and a
|
||||
@tech{KeyEvent} for every keystroke the user of the computer makes. The result
|
||||
of the call becomes the current world.
|
||||
|
@ -288,7 +288,7 @@ All @tech{MouseEvent}s are represented via symbols:
|
|||
@defform[(on-mouse clack-expr)
|
||||
#:contracts
|
||||
([clack-expr
|
||||
(-> (unsyntax @tech{World}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent}) (unsyntax @tech{World}))])]{
|
||||
(-> (unsyntax @tech{WorldState}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent}) (unsyntax @tech{WorldState}))])]{
|
||||
tell DrScheme to call @scheme[clack-expr] on the current world, the current
|
||||
@scheme[x] and @scheme[y] coordinates of the mouse, and and a
|
||||
@tech{MouseEvent} for every (noticeable) action of the mouse by the
|
||||
|
@ -303,7 +303,7 @@ All @tech{MouseEvent}s are represented via symbols:
|
|||
|
||||
@defform[(on-draw render-expr)
|
||||
#:contracts
|
||||
([render-expr (-> (unsyntax @tech{World}) scene?)])]{
|
||||
([render-expr (-> (unsyntax @tech{WorldState}) scene?)])]{
|
||||
|
||||
tell DrScheme to call the function @scheme[render-expr] whenever the
|
||||
canvas must be drawn. The external canvas is usually re-drawn after DrScheme has
|
||||
|
@ -312,7 +312,7 @@ All @tech{MouseEvent}s are represented via symbols:
|
|||
|
||||
@defform/none[(on-draw render-expr width-expr height-expr)
|
||||
#:contracts
|
||||
([render-expr (-> (unsyntax @tech{World}) scene?)]
|
||||
([render-expr (-> (unsyntax @tech{WorldState}) scene?)]
|
||||
[width-expr natural-number/c]
|
||||
[height-expr natural-number/c])]{
|
||||
|
||||
|
@ -325,7 +325,7 @@ All @tech{MouseEvent}s are represented via symbols:
|
|||
|
||||
@defform[(stop-when last-world?)
|
||||
#:contracts
|
||||
([last-world? (-> (unsyntax @tech{World}) boolean?)])]{
|
||||
([last-world? (-> (unsyntax @tech{WorldState}) boolean?)])]{
|
||||
tell DrScheme to call the @scheme[last-world?] function whenever the canvas is
|
||||
drawn. If this call produces @scheme[true], the world program is shut
|
||||
down. Specifically, the clock is stopped; no more
|
||||
|
@ -436,7 +436,8 @@ it to the locked position; and}
|
|||
Simulating any dynamic behavior via a @tech{world} program demands two
|
||||
different activities. First, we must tease out those portions of our
|
||||
domain that change over time or in reaction to actions, and we must
|
||||
develop a data representation @deftech{D} for this information. Keep in
|
||||
develop a data representation for this information. This is what we call
|
||||
@tech{WorldState}. Keep in
|
||||
mind that a good data definition makes it easy for readers to map data to
|
||||
information in the real world and vice versa. For all others aspects of
|
||||
the world, we use global constants, including graphical or visual
|
||||
|
@ -447,7 +448,7 @@ Second, we must translate the actions in our domain---the arrows in the
|
|||
teachpack can deal with. Once we have decided to use the passing of time
|
||||
for one aspect, key presses for another, and mouse movements for a third,
|
||||
we must develop functions that map the current state of the
|
||||
world---represented as data from @tech{D}---into the next state of the
|
||||
world---represented as data from @tech{WorldState}---into the next state of the
|
||||
world. Put differently, we have just created a wish list with three
|
||||
handler functions that have the following general contract and purpose
|
||||
statements:
|
||||
|
@ -455,16 +456,16 @@ Second, we must translate the actions in our domain---the arrows in the
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
;; tick : @tech{D} -> @tech{D}
|
||||
;; tick : WorldState -> WorldState
|
||||
;; deal with the passing of time
|
||||
(define (tick w) ...)
|
||||
|
||||
;; click : @tech{D} @emph{Number} @emph{Number} @tech{MouseEvent} -> @tech{D}
|
||||
;; click : WorldState @emph{Number} @emph{Number} @tech{MouseEvent} -> WorldState
|
||||
;; deal with a mouse click at @emph{(x,y)} of kind @emph{me}
|
||||
;; in the current world @emph{w}
|
||||
(define (click w x y me) ...)
|
||||
|
||||
;; control : @tech{D} @tech{KeyEvent} -> @tech{D}
|
||||
;; control : WorldState @tech{KeyEvent} -> WorldState
|
||||
;; deal with a key event (symbol, char) @emph{ke}
|
||||
;; in the current world @emph{w}
|
||||
(define (control w ke) ...)
|
||||
|
@ -487,15 +488,14 @@ Our first and immediate goal is to represent the world as data. In this
|
|||
the door is whether it is locked, unlocked but closed, or open. We use
|
||||
three symbols to represent the three states:
|
||||
|
||||
@deftech{SD} : state of door
|
||||
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
;; The state of the door (SD) is one of:
|
||||
;; WorldState is one of:
|
||||
;; -- @scheme['locked]
|
||||
;; -- @scheme['closed]
|
||||
;; -- @scheme['open]
|
||||
;; interpretation: state of door
|
||||
))
|
||||
|
||||
Symbols are particularly well-suited here because they directly express
|
||||
|
@ -535,14 +535,14 @@ a visible scene.}
|
|||
|
||||
]
|
||||
|
||||
Let's start with @emph{automatic-closer}. Substituting @tech{SD} for
|
||||
@tech{D} and @emph{automatic-closer} for @emph{tick}, we get its contract,
|
||||
Let's start with @emph{automatic-closer}. Since @emph{automatic-closer}
|
||||
acts as the @scheme[on-tick] handler, we get its contract,
|
||||
and it is easy to refine the purpose statement, too:
|
||||
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
;; automatic-closer : @tech{SD} -> @tech{SD}
|
||||
;; automatic-closer : WorldState -> WorldState
|
||||
;; closes an open door over the period of one tick
|
||||
(define (automatic-closer state-of-door) ...)
|
||||
))
|
||||
|
@ -560,7 +560,7 @@ and it is easy to refine the purpose statement, too:
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
;; automatic-closer : @tech{SD} -> @tech{SD}
|
||||
;; automatic-closer : WorldState -> WorldState
|
||||
;; closes an open door over the period of one tick
|
||||
|
||||
(check-expect (automatic-closer 'locked) 'locked)
|
||||
|
@ -604,7 +604,7 @@ For the remaining three arrows of the diagram, we design a function that
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
;; door-actions : @tech{SD} @tech{KeyEvent} -> @tech{SD}
|
||||
;; door-actions : WorldState @tech{KeyEvent} -> WorldState
|
||||
;; key events simulate actions on the door
|
||||
(define (door-actions s k) ...)
|
||||
))
|
||||
|
@ -644,7 +644,7 @@ purpose:
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
;; render : @tech{SD} -> @tech{scene}
|
||||
;; render : WorldState -> @tech{scene}
|
||||
;; translate the current state of the door into a large text
|
||||
(define (render s)
|
||||
(text (symbol->string s) 40 'red))
|
||||
|
@ -719,9 +719,9 @@ Note the last clause includes @scheme[empty] of course.
|
|||
|
||||
Each world-producing callback in a world program---those for handling clock
|
||||
tick events, keyboard events, and mouse events---may produce a
|
||||
@tech{Package} in addition to just a @tech{World}.
|
||||
@tech{Package} in addition to just a @tech{WorldState}.
|
||||
|
||||
@deftech{Package} represents a pair consisting of a @tech{World} (state)
|
||||
@deftech{Package} represents a pair consisting of a @tech{WorldState}
|
||||
and a message from a @tech{world} program to the @tech{server}. Because
|
||||
programs only send messages via @tech{Package}, the teachpack does not
|
||||
provide the selectors for the structure, only the constructor and a
|
||||
|
@ -731,38 +731,38 @@ Each world-producing callback in a world program---those for handling clock
|
|||
determine whether @scheme[x] is a @tech{Package}.}
|
||||
|
||||
@defproc[(make-package [w any/c][m sexp?]) package?]{
|
||||
create a @tech{Package} from a @tech{World} and an @tech{S-expression}.}
|
||||
create a @tech{Package} from a @tech{WorldState} and an @tech{S-expression}.}
|
||||
|
||||
As mentioned, all event handlers may return @tech{World}s or @tech{Package}s;
|
||||
As mentioned, all event handlers may return @tech{WorldState}s or @tech{Package}s;
|
||||
here are the revised specifications:
|
||||
|
||||
@defform/none[(on-tick tick-expr)
|
||||
#:contracts
|
||||
([tick-expr (-> (unsyntax @tech{World}) (or/c (unsyntax @tech{World}) package?))])]{
|
||||
([tick-expr (-> (unsyntax @tech{WorldState}) (or/c (unsyntax @tech{WorldState}) package?))])]{
|
||||
}
|
||||
|
||||
@defform/none[(on-tick tick-expr rate-expr)
|
||||
#:contracts
|
||||
([tick-expr (-> (unsyntax @tech{World}) (or/c (unsyntax @tech{World}) package?))]
|
||||
([tick-expr (-> (unsyntax @tech{WorldState}) (or/c (unsyntax @tech{WorldState}) package?))]
|
||||
[rate-expr natural-number/c])]{
|
||||
}
|
||||
|
||||
@defform/none[(on-key change-expr)
|
||||
#:contracts
|
||||
([change-expr (-> (unsyntax @tech{World}) key-event? (or/c (unsyntax @tech{World}) package?))])]{
|
||||
([change-expr (-> (unsyntax @tech{WorldState}) key-event? (or/c (unsyntax @tech{WorldState}) package?))])]{
|
||||
}
|
||||
|
||||
@defform/none[(on-mouse clack-expr)
|
||||
#:contracts
|
||||
([clack-expr
|
||||
(-> (unsyntax @tech{World}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent})
|
||||
(or/c (unsyntax @tech{World}) package?))])]{
|
||||
(-> (unsyntax @tech{WorldState}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent})
|
||||
(or/c (unsyntax @tech{WorldState}) package?))])]{
|
||||
}
|
||||
|
||||
If one of these event handlers produces a @tech{Package}, the content of the world
|
||||
field becomes the next world and the message field specifies what the
|
||||
world sends to the universe. This distinction also explains why the data
|
||||
definition for @tech{World} may not include a @tech{Package}.
|
||||
definition for @tech{WorldState} may not include a @tech{Package}.
|
||||
|
||||
@subsection{Connecting with the Universe}
|
||||
|
||||
|
@ -823,14 +823,14 @@ The @scheme[on-receive] clause of a @scheme[big-bang] specifies the event handle
|
|||
|
||||
@defform[(on-receive receive-expr)
|
||||
#:contracts
|
||||
([receive-expr (-> (unsyntax @tech{World}) sexp? (or/c (unsyntax @tech{World}) package?))])]{
|
||||
([receive-expr (-> (unsyntax @tech{WorldState}) sexp? (or/c (unsyntax @tech{WorldState}) package?))])]{
|
||||
tell DrScheme to call @scheme[receive-expr] for every message receipt, on the current
|
||||
@tech{World} and the received message. The result of the call becomes the current
|
||||
@tech{World}.
|
||||
@tech{WorldState} and the received message. The result of the call becomes the current
|
||||
@tech{WorldState}.
|
||||
|
||||
Because @scheme[receive-expr] is (or evaluates to) a world-transforming
|
||||
function, it too can produce a @tech{Package} instead of just a
|
||||
@tech{World}. If the result is a @tech{Package}, its message content is
|
||||
@tech{WorldState}. If the result is a @tech{Package}, its message content is
|
||||
sent to the @tech{server}.}
|
||||
|
||||
The diagram below summarizes the extensions of this section in graphical form.
|
||||
|
@ -842,9 +842,9 @@ A registered world program may send a message to the universe server
|
|||
message is transmitted to the server, which may forward it to some
|
||||
other world program as given or in some massaged form. The arrival of a
|
||||
message is just another event that a world program must deal with. Like
|
||||
all other event handlers @emph{receive} accepts a @tech{World} and some
|
||||
all other event handlers @emph{receive} accepts a @tech{WorldState} and some
|
||||
auxiliary arguments (a message in this case) and produces a
|
||||
@tech{World} or a @tech{Package}.
|
||||
@tech{WorldState} or a @tech{Package}.
|
||||
|
||||
When messages are sent from any of the worlds to the universe or vice versa,
|
||||
there is no need for the sender and receiver to synchronize. Indeed, a sender
|
||||
|
@ -961,7 +961,7 @@ A @tech{server} keeps track of information about the @tech{universe} that
|
|||
represented depends on the situation and the programmer, just as with
|
||||
@tech{world} programs.
|
||||
|
||||
@deftech{Universe} @scheme[any/c] represent the server's state For running
|
||||
@deftech{UniverseState} @scheme[any/c] represent the server's state For running
|
||||
@tech{universe}s, the teachpack demands that you come up with a data
|
||||
definition for (your state of the) @tech{server}. Any piece of data can
|
||||
represent the state. We just assume that you introduce a data definition
|
||||
|
@ -1010,16 +1010,16 @@ description. Two of them are mandatory:
|
|||
@item{
|
||||
@defform[(on-new new-expr)
|
||||
#:contracts
|
||||
([new-expr (-> (unsyntax @tech{Universe}) world?
|
||||
(cons (unsyntax @tech{Universe}) [listof mail?]))])]{
|
||||
([new-expr (-> (unsyntax @tech{UniverseState}) world?
|
||||
(cons (unsyntax @tech{UniverseState}) [listof mail?]))])]{
|
||||
tell DrScheme to call the function @scheme[new-expr] every time another world joins the
|
||||
universe.}}
|
||||
|
||||
@item{
|
||||
@defform[(on-msg msg-expr)
|
||||
#:contracts
|
||||
([msg-expr (-> (unsyntax @tech{Universe}) world? sexp?
|
||||
(cons (unsyntax @tech{Universe}) [listof mail?]))])]{
|
||||
([msg-expr (-> (unsyntax @tech{UniverseState}) world? sexp?
|
||||
(cons (unsyntax @tech{UniverseState}) [listof mail?]))])]{
|
||||
|
||||
tell DrScheme to apply @scheme[msg-expr] to the current state of the universe, the world
|
||||
that sent the message, and the message itself. The handler must produce a state of the
|
||||
|
@ -1039,7 +1039,7 @@ optional handlers:
|
|||
@item{
|
||||
@defform/none[(on-tick tick-expr)
|
||||
#:contracts
|
||||
([tick-expr (-> (unsyntax @tech{Universe}) bundle?)])]{
|
||||
([tick-expr (-> (unsyntax @tech{UniverseState}) bundle?)])]{
|
||||
tell DrScheme to apply @scheme[tick-expr] to the current state of the
|
||||
universe. The handler is expected to produce a bundle of the new state of
|
||||
the universe and a list of mails.
|
||||
|
@ -1047,7 +1047,7 @@ optional handlers:
|
|||
|
||||
@defform/none[(on-tick tick-expr rate-expr)
|
||||
#:contracts
|
||||
([tick-expr (-> (unsyntax @tech{Universe}) bundle?)]
|
||||
([tick-expr (-> (unsyntax @tech{UniverseState}) bundle?)]
|
||||
[rate-expr natural-number/c])]{
|
||||
tell DrScheme to apply @scheme[tick-expr] as above but use the specified
|
||||
clock tick rate instead of the default.
|
||||
|
@ -1057,7 +1057,7 @@ optional handlers:
|
|||
@item{
|
||||
@defform[(on-disconnect dis-expr)
|
||||
#:contracts
|
||||
([dis-expr (-> (unsyntax @tech{Universe}) world? bundle?)])]{
|
||||
([dis-expr (-> (unsyntax @tech{UniverseState}) world? bundle?)])]{
|
||||
tell DrScheme to invoke @scheme[dis-expr] every time a participating
|
||||
@tech{world} drops its connection to the server. The first argument is the
|
||||
current state of the universe; the second one is the world that got
|
||||
|
@ -1068,7 +1068,7 @@ optional handlers:
|
|||
@item{
|
||||
@defform[(to-string render-expr)
|
||||
#:contracts
|
||||
([render-expr (-> (unsyntax @tech{Universe}) string?)])]{
|
||||
([render-expr (-> (unsyntax @tech{UniverseState}) string?)])]{
|
||||
tell DrScheme to render the state of the universe after each event and to
|
||||
display this string in the universe console.
|
||||
}
|
||||
|
@ -1134,7 +1134,7 @@ In summary, the first step of a protocol design is to introduce:
|
|||
@itemize[
|
||||
|
||||
@item{a data definition for the information about the universe that the
|
||||
server tracks, call it @tech{Universe};}
|
||||
server tracks, call it @tech{UniverseState};}
|
||||
|
||||
@item{a data definition for the world(s) about their current relationship
|
||||
to the universe;}
|
||||
|
@ -1172,13 +1172,13 @@ translates into the design of two functions with the following headers,
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
;; @tech{Universe} World -> (make-bundle @tech{Universe} [Listof mail?])
|
||||
;; create new @tech{Universe} when world w is joining the universe,
|
||||
;; @tech{UniverseState} world? -> (make-bundle @tech{UniverseState} [Listof mail?])
|
||||
;; create new @tech{UniverseState} when world w is joining the universe,
|
||||
;; which is in state s; also send mails as needed
|
||||
(define (add-world s w) ...)
|
||||
|
||||
;; @tech{Universe} World MsgW2U -> (make-bundle @tech{Universe} [Listof mail?])
|
||||
;; create new @tech{Universe} when world w is sending message m
|
||||
;; @tech{UniverseState} world? MsgW2U -> (make-bundle @tech{UniverseState} [Listof mail?])
|
||||
;; create new @tech{UniverseState} when world w is sending message m
|
||||
;; to universe in state s; also send mails as needed
|
||||
(define (process s p m) ...)
|
||||
))
|
||||
|
@ -1205,7 +1205,7 @@ As for the server's state, it must obviously keep track of all @tech{world}s tha
|
|||
no @tech{world}s and, at that point, the server has nothing to track.
|
||||
|
||||
While there are many different useful ways of representing such a @tech{universe},
|
||||
we choose to introduce @tech{Universe} as a list of @tech{world}s, and we
|
||||
we choose to introduce @tech{UniverseState} as a list of @tech{world}s, and we
|
||||
interpret non-empty lists as those where the first @tech{world} is active and the
|
||||
remainder are the passive @tech{world}s. As for the two possible events,
|
||||
@itemize[
|
||||
|
@ -1249,7 +1249,7 @@ The preceding subsection dictates that our server program starts like this:
|
|||
[schemeblock
|
||||
;; teachpack: universe.ss
|
||||
|
||||
;; Universe is [Listof world?]
|
||||
;; UniverseState is [Listof world?]
|
||||
;; StopMessage is 'done.
|
||||
;; GoMessage is 'it-is-your-turn.
|
||||
])
|
||||
|
@ -1264,13 +1264,14 @@ The preceding subsection dictates that our server program starts like this:
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
[schemeblock
|
||||
;; Result is (make-bundle Universe (list (make-mail world? GoMessage)))
|
||||
;; Result is
|
||||
;; (make-bundle UniverseState (list (make-mail world? GoMessage)))
|
||||
|
||||
;; Universe world? -> Result
|
||||
;; UniverseState world? -> Result
|
||||
;; add world w to the universe, when server is in state u
|
||||
(define (add-world u w) ...)
|
||||
|
||||
;; Universe world? StopMessage -> Result
|
||||
;; UniverseState world? StopMessage -> Result
|
||||
;; world w sent message m when server is in state u
|
||||
(define (switch u w m) ...)
|
||||
])
|
||||
|
@ -1279,7 +1280,7 @@ Although we could have re-used the generic contracts from this
|
|||
documentation, we also know from our protocol that our server sends a
|
||||
message to exactly one world. For this reason, both functions return the
|
||||
same kind of result: a bundle that contains the new state of the server
|
||||
(@tech{Universe}) and a list that contains a single mail. These contracts
|
||||
(@tech{UniverseState}) and a list that contains a single mail. These contracts
|
||||
are just refinements of the generic ones. (A type-oriented programmer would
|
||||
say that the contracts here are subtypes of the generic ones.)
|
||||
|
||||
|
@ -1311,7 +1312,7 @@ protocol.
|
|||
|
||||
The protocol tells us that @emph{add-world} just adds the given
|
||||
@emph{world} structure---recall that this a data representation of the
|
||||
actual @tech{world} program---to the @tech{Universe} and then sends a
|
||||
actual @tech{world} program---to the @tech{UniverseState} and then sends a
|
||||
message to the first world on this list to get things going:
|
||||
|
||||
@(begin
|
||||
|
@ -1338,11 +1339,12 @@ Similarly, the protocol says that when @emph{switch} is invoked because a
|
|||
[schemeblock
|
||||
(define (switch univ wrld m)
|
||||
(local ((define univ* (append (rest univ) (list (first univ)))))
|
||||
(make-bundle univ* (list (make-mail (first univ*) 'it-is-your-turn)))))
|
||||
(make-bundle univ*
|
||||
(list (make-mail (first univ*) 'it-is-your-turn)))))
|
||||
])
|
||||
|
||||
As before, appending the first world to the end of the list guarantees
|
||||
that there is at least this one world on the next @tech{Universe}
|
||||
that there is at least this one world on the next @tech{UniverseState}
|
||||
(state). It is therefore acceptable to create a mail for this world.
|
||||
|
||||
Exercise: The function definition simply assumes that @emph{wrld} is
|
||||
|
@ -1371,31 +1373,35 @@ The final step is to design the ball @tech{world}. Recall that each world
|
|||
(schemeblock
|
||||
;; teachpack: universe.ss
|
||||
|
||||
;; World is one of
|
||||
;; WorldState is one of:
|
||||
;; -- Number %% representing the @emph{y} coordinate
|
||||
;; -- @scheme['resting]
|
||||
|
||||
(define WORLD0 'resting)
|
||||
|
||||
;; A WorldResult is one of:
|
||||
;; -- WorldState
|
||||
;; -- (make-package WorldState StopMessage)
|
||||
))
|
||||
The definition says that initially a @tech{world} is passive.
|
||||
|
||||
The communication protocol and the refined data definition of @tech{World}
|
||||
The communication protocol and the refined data definition of @tech{WorldState}
|
||||
imply a number of contract and purpose statements:
|
||||
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
|
||||
;; World GoMessage -> World or (make-package World StopMessage)
|
||||
;; WorldState GoMessage -> WorldResult
|
||||
;; make sure the ball is moving
|
||||
(define (receive w n) ...)
|
||||
|
||||
;; World -> World or (make-package World StopMessage)
|
||||
;; WorldState -> WorldResult
|
||||
;; move this ball upwards for each clock tick
|
||||
;; or stay @scheme['resting]
|
||||
(define (move w) ...)
|
||||
|
||||
;; World -> Scene
|
||||
;; WorldState -> Scene
|
||||
;; render the world as a scene
|
||||
(define (render w) ...)
|
||||
))
|
||||
|
@ -1403,7 +1409,7 @@ The communication protocol and the refined data definition of @tech{World}
|
|||
Let's design one function at a time, starting with @emph{receive}. Since
|
||||
the protocol doesn't spell out what @emph{receive} is to compute, let's
|
||||
create a good set of functional examples, exploiting the structure of the
|
||||
data organization of @tech{World}:
|
||||
data organization of @tech{WorldState}:
|
||||
|
||||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
|
@ -1458,7 +1464,7 @@ the scene every time @scheme['it-is-your-turn] is received. Design this function
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
; World -> World or @scheme[(make-package 'resting 'done)]
|
||||
; WorldState -> WorldState or @scheme[(make-package 'resting 'done)]
|
||||
; move the ball if it is flying
|
||||
|
||||
(check-expect (move 'resting) 'resting)
|
||||
|
@ -1498,7 +1504,7 @@ Finally, here is the third function, which renders the state as a scene:
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
; World -> Scene
|
||||
; WorldState -> Scene
|
||||
; render the state of the world as a scene
|
||||
|
||||
(check-expect (render HEIGHT) (place-image BALL 50 HEIGHT MT))
|
||||
|
@ -1520,7 +1526,7 @@ Finally, here is the third function, which renders the state as a scene:
|
|||
@(begin
|
||||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
; String -> (World -> Scene)
|
||||
; String -> (WorldState -> Scene)
|
||||
; render the state of the world as a scene
|
||||
|
||||
(check-expect
|
||||
|
@ -1545,7 +1551,7 @@ Finally, here is the third function, which renders the state as a scene:
|
|||
#reader scribble/comment-reader
|
||||
(schemeblock
|
||||
|
||||
; String -> World
|
||||
; String -> WorldState
|
||||
; create and hook up a world with the @scheme[LOCALHOST] server
|
||||
(define (create-world name)
|
||||
(big-bang WORLD0
|
||||
|
|
Loading…
Reference in New Issue
Block a user