svn: r13056
This commit is contained in:
parent
38ef7d3c41
commit
a6f08c7399
|
@ -915,6 +915,9 @@ Understanding the server's event handling functions demands three
|
||||||
@defproc[(world=? [u world?][v world?]) boolean?]{
|
@defproc[(world=? [u world?][v world?]) boolean?]{
|
||||||
compares two @emph{world}s for equality.}
|
compares two @emph{world}s for equality.}
|
||||||
|
|
||||||
|
defproc[(world-name [w world?]) symbol?]{
|
||||||
|
extracts the name from a @emph{world} structure.}
|
||||||
|
|
||||||
@defthing[world1 world?]{a world for testing your programs}
|
@defthing[world1 world?]{a world for testing your programs}
|
||||||
@defthing[world2 world?]{another world for testing your programs}
|
@defthing[world2 world?]{another world for testing your programs}
|
||||||
@defthing[world3 world?]{and a third one}
|
@defthing[world3 world?]{and a third one}
|
||||||
|
@ -941,14 +944,14 @@ structures:
|
||||||
|
|
||||||
@item{Each event handler produces a @emph{bundle}, which is a structure
|
@item{Each event handler produces a @emph{bundle}, which is a structure
|
||||||
that contains the @tech{server}'s state and a list of mails to other
|
that contains the @tech{server}'s state and a list of mails to other
|
||||||
worlds. Again, the teachpack provides only the predicate and a constructor:
|
worlds. Again, the teachpack provides only the predicate and a constructor:
|
||||||
|
|
||||||
@defproc[(bundle? [x any/c]) boolean?]{
|
@defproc[(bundle? [x any/c]) boolean?]{
|
||||||
determines whether @scheme[x] is a @emph{bundle}.}
|
determines whether @scheme[x] is a @emph{bundle}.}
|
||||||
|
|
||||||
@defproc[(make-bundle [state any/c] [mails (listof mail?)]) bundle?]{
|
@defproc[(make-bundle [listof world?] [state any/c] [mails (listof mail?)]) bundle?]{
|
||||||
creates a @emph{bundle} from a piece of data that represents a server
|
creates a @emph{bundle} from a list of worlds, a piece of data that represents a server
|
||||||
state and a list of mails.}
|
state, and a list of mails.}
|
||||||
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1001,7 +1004,6 @@ A @scheme[universe] expression starts a server. Visually it opens
|
||||||
especially useful during the integration of the various pieces of a
|
especially useful during the integration of the various pieces of a
|
||||||
distributed program.
|
distributed program.
|
||||||
|
|
||||||
|
|
||||||
Now it is possible to explain the clauses in a @scheme[universe] server
|
Now it is possible to explain the clauses in a @scheme[universe] server
|
||||||
description. Two of them are mandatory:
|
description. Two of them are mandatory:
|
||||||
|
|
||||||
|
@ -1010,22 +1012,26 @@ description. Two of them are mandatory:
|
||||||
@item{
|
@item{
|
||||||
@defform[(on-new new-expr)
|
@defform[(on-new new-expr)
|
||||||
#:contracts
|
#:contracts
|
||||||
([new-expr (-> (unsyntax @tech{UniverseState}) world?
|
([new-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? bundle?)])]{
|
||||||
(cons (unsyntax @tech{UniverseState}) [listof mail?]))])]{
|
|
||||||
tell DrScheme to call the function @scheme[new-expr] every time another world joins the
|
tell DrScheme to call the function @scheme[new-expr] every time another world joins the
|
||||||
universe.}}
|
universe. The event handler is called on the current list of worlds and the
|
||||||
|
joining world.
|
||||||
|
}}
|
||||||
|
|
||||||
@item{
|
@item{
|
||||||
@defform[(on-msg msg-expr)
|
@defform[(on-msg msg-expr)
|
||||||
#:contracts
|
#:contracts
|
||||||
([msg-expr (-> (unsyntax @tech{UniverseState}) world? sexp?
|
([msg-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? sexp? bundle?)])]{
|
||||||
(cons (unsyntax @tech{UniverseState}) [listof mail?]))])]{
|
|
||||||
|
|
||||||
tell DrScheme to apply @scheme[msg-expr] to the current state of the universe, the world
|
tell DrScheme to apply @scheme[msg-expr] to the list of currently
|
||||||
that sent the message, and the message itself. The handler must produce a state of the
|
participating worlds, the current state of the universe, the world
|
||||||
universe and a list of mails.}
|
that sent the message, and the message itself.}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
All event handlers produce a @emph{bundle}. The list of worlds in this
|
||||||
|
@emph{bundle} becomes the server's list of worlds; the state in the bundle
|
||||||
|
is safe-guarded by the server until the next event; and the mails are
|
||||||
|
broadcast as specified.
|
||||||
|
|
||||||
The following picture provides a graphical overview of the server's workings.
|
The following picture provides a graphical overview of the server's workings.
|
||||||
|
|
||||||
|
@ -1039,36 +1045,37 @@ optional handlers:
|
||||||
@item{
|
@item{
|
||||||
@defform/none[(on-tick tick-expr)
|
@defform/none[(on-tick tick-expr)
|
||||||
#:contracts
|
#:contracts
|
||||||
([tick-expr (-> (unsyntax @tech{UniverseState}) bundle?)])]{
|
([tick-expr (-> [listof world?] (unsyntax @tech{UniverseState}) bundle?)])]{
|
||||||
tell DrScheme to apply @scheme[tick-expr] to the current state of the
|
tell DrScheme to apply @scheme[tick-expr] to the current list of
|
||||||
universe. The handler is expected to produce a bundle of the new state of
|
participating worlds and the current state of the
|
||||||
the universe and a list of mails.
|
universe.
|
||||||
}
|
}
|
||||||
|
|
||||||
@defform/none[(on-tick tick-expr rate-expr)
|
@defform/none[(on-tick tick-expr rate-expr)
|
||||||
#:contracts
|
#:contracts
|
||||||
([tick-expr (-> (unsyntax @tech{UniverseState}) bundle?)]
|
([tick-expr (-> [listof world?] (unsyntax @tech{UniverseState}) bundle?)]
|
||||||
[rate-expr natural-number/c])]{
|
[rate-expr natural-number/c])]{
|
||||||
tell DrScheme to apply @scheme[tick-expr] as above but use the specified
|
tell DrScheme to apply @scheme[tick-expr] as above but use the specified
|
||||||
clock tick rate instead of the default.
|
clock tick rate instead of the default.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@item{
|
@item{
|
||||||
@defform[(on-disconnect dis-expr)
|
@defform[(on-disconnect dis-expr)
|
||||||
#:contracts
|
#:contracts
|
||||||
([dis-expr (-> (unsyntax @tech{UniverseState}) world? bundle?)])]{
|
([dis-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? bundle?)])]{
|
||||||
tell DrScheme to invoke @scheme[dis-expr] every time a participating
|
tell DrScheme to invoke @scheme[dis-expr] every time a participating
|
||||||
@tech{world} drops its connection to the server. The first argument is the
|
@tech{world} drops its connection to the server. The first two arguments
|
||||||
current state of the universe; the second one is the world that got
|
are the current list of participating worlds and the state of the
|
||||||
disconnected.
|
universe; the third one is the world that got disconnected.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@item{
|
@item{
|
||||||
@defform[(to-string render-expr)
|
@defform[(to-string render-expr)
|
||||||
#:contracts
|
#:contracts
|
||||||
([render-expr (-> (unsyntax @tech{UniverseState}) string?)])]{
|
([render-expr (-> [listof world?] (unsyntax @tech{UniverseState}) string?)])]{
|
||||||
tell DrScheme to render the state of the universe after each event and to
|
tell DrScheme to render the state of the universe after each event and to
|
||||||
display this string in the universe console.
|
display this string in the universe console.
|
||||||
}
|
}
|
||||||
|
@ -1179,18 +1186,18 @@ translates into the design of two functions with the following headers,
|
||||||
@(begin
|
@(begin
|
||||||
#reader scribble/comment-reader
|
#reader scribble/comment-reader
|
||||||
(schemeblock
|
(schemeblock
|
||||||
;; @tech{UniverseState} world? -> (make-bundle @tech{UniverseState} [Listof mail?])
|
;; @tech{UniverseState} world? -> (make-bundle [Listof world?] @tech{UniverseState} [Listof mail?])
|
||||||
;; create new @tech{UniverseState} when world w is joining the universe,
|
;; create new @tech{UniverseState} when world w is joining the universe,
|
||||||
;; which is in state s; also send mails as needed
|
;; which is in state s; also send mails as needed
|
||||||
(define (add-world s w) ...)
|
(define (add-world s w) ...)
|
||||||
|
|
||||||
;; @tech{UniverseState} world? MsgW2U -> (make-bundle @tech{UniverseState} [Listof mail?])
|
;; @tech{UniverseState} world? MsgW2U -> (make-bundle [Listof world?] @tech{UniverseState} [Listof mail?])
|
||||||
;; create new @tech{UniverseState} when world w is sending message m
|
;; create new @tech{UniverseState} when world w is sending message m
|
||||||
;; to universe in state s; also send mails as needed
|
;; to universe in state s; also send mails as needed
|
||||||
(define (process s p m) ...)
|
(define (process s p m) ...)
|
||||||
))
|
))
|
||||||
|
|
||||||
Note how both functions return a bundle.
|
Note how both functions return a @emph{bundle}.
|
||||||
|
|
||||||
Finally, we must also decide how the messages affect the states of the
|
Finally, we must also decide how the messages affect the states of the
|
||||||
worlds; which of their callback may send messages and when; and what to do
|
worlds; which of their callback may send messages and when; and what to do
|
||||||
|
@ -1272,7 +1279,7 @@ The preceding subsection dictates that our server program starts like this:
|
||||||
#reader scribble/comment-reader
|
#reader scribble/comment-reader
|
||||||
[schemeblock
|
[schemeblock
|
||||||
;; Result is
|
;; Result is
|
||||||
;; (make-bundle UniverseState (list (make-mail world? GoMessage)))
|
;; (make-bundle [Listof world?] UniverseState (list (make-mail world? GoMessage)))
|
||||||
|
|
||||||
;; UniverseState world? -> Result
|
;; UniverseState world? -> Result
|
||||||
;; add world w to the universe, when server is in state u
|
;; add world w to the universe, when server is in state u
|
||||||
|
@ -1298,14 +1305,14 @@ The second step of the design recipe calls for functional examples:
|
||||||
[schemeblock
|
[schemeblock
|
||||||
;; an obvious example for adding a world:
|
;; an obvious example for adding a world:
|
||||||
(check-expect
|
(check-expect
|
||||||
(add-world '() world1)
|
(add-world '() '* world1)
|
||||||
(make-bundle (list world1)
|
(make-bundle (list world1) '*
|
||||||
(list (make-mail world1 'it-is-your-turn))))
|
(list (make-mail world1 'it-is-your-turn))))
|
||||||
|
|
||||||
;; an example for receiving a message from the active world:
|
;; an example for receiving a message from the active world:
|
||||||
(check-expect
|
(check-expect
|
||||||
(switch (list world1 world2) world1 'it-is-your-turn)
|
(switch (list world1 world2) '* world1 'it-is-your-turn)
|
||||||
(make-bundle (list world2 world1)
|
(make-bundle (list world2 world1) '*
|
||||||
(list (make-mail world2 'it-is-your-turn))))
|
(list (make-mail world2 'it-is-your-turn))))
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -1327,7 +1334,7 @@ message to the first world on this list to get things going:
|
||||||
[schemeblock
|
[schemeblock
|
||||||
(define (add-world univ wrld)
|
(define (add-world univ wrld)
|
||||||
(local ((define univ* (append univ (list wrld))))
|
(local ((define univ* (append univ (list wrld))))
|
||||||
(make-bundle univ*
|
(make-bundle univ* '*
|
||||||
(list (make-mail (first univ*) 'it-is-your-turn)))))
|
(list (make-mail (first univ*) 'it-is-your-turn)))))
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -1346,7 +1353,7 @@ Similarly, the protocol says that when @emph{switch} is invoked because a
|
||||||
[schemeblock
|
[schemeblock
|
||||||
(define (switch univ wrld m)
|
(define (switch univ wrld m)
|
||||||
(local ((define univ* (append (rest univ) (list (first univ)))))
|
(local ((define univ* (append (rest univ) (list (first univ)))))
|
||||||
(make-bundle univ*
|
(make-bundle univ* '*
|
||||||
(list (make-mail (first univ*) 'it-is-your-turn)))))
|
(list (make-mail (first univ*) 'it-is-your-turn)))))
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user