From c22b57000402ce4499613767dbcd87351459186e Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Mon, 12 Jan 2009 17:30:44 +0000 Subject: [PATCH] svn: r13071 --- .../teachpack/2htdp/scribblings/server2.ss | 2 +- .../2htdp/scribblings/universe.scrbl | 92 ++++++++++-------- collects/teachpack/world.png | Bin 19925 -> 0 bytes 3 files changed, 52 insertions(+), 42 deletions(-) delete mode 100644 collects/teachpack/world.png diff --git a/collects/teachpack/2htdp/scribblings/server2.ss b/collects/teachpack/2htdp/scribblings/server2.ss index 427a7c22ed..2bf45e143c 100644 --- a/collects/teachpack/2htdp/scribblings/server2.ss +++ b/collects/teachpack/2htdp/scribblings/server2.ss @@ -10,7 +10,7 @@ (define program (apply vl-append (map (lambda (t) (text t '() (- FT 2))) - (list (format "(universe ~a ~a)" initialize proc-msg))))) + (list (format "(universe [on-new ~a] [on-msg ~a])" initialize proc-msg))))) (define Program (cc-superimpose diff --git a/collects/teachpack/2htdp/scribblings/universe.scrbl b/collects/teachpack/2htdp/scribblings/universe.scrbl index 044a6f82d8..d16ed79e53 100644 --- a/collects/teachpack/2htdp/scribblings/universe.scrbl +++ b/collects/teachpack/2htdp/scribblings/universe.scrbl @@ -835,7 +835,7 @@ The @scheme[on-receive] clause of a @scheme[big-bang] specifies the event handle The diagram below summarizes the extensions of this section in graphical form. -@image["universe.png"] +@image["world.png"] A registered world program may send a message to the universe server at any time by returning a @tech{Package} from an event handler. The @@ -853,16 +853,15 @@ When messages are sent from any of the worlds to the universe or vice versa, the receiving @tech{server} or @tech{world} program take care of them. @; ----------------------------------------------------------------------------- - @section[#:tag "universe-server"]{The Universe Server} A @deftech{server} is the central control program of a @tech{universe} and deals with receiving and sending of messages between the world programs that participate in the @tech{universe}. Like a @tech{world} program, a server is a program that reacts to events, though to different - events. There are two primary kinds of events: when a new @tech{world} - program joins the @tech{universe} that the server controls and when a - @tech{world} sends a message. + events than @tech{world}s. The two primary kinds of events are the + appearance of a new @tech{world} program in the @tech{universe} + and the receipt of a message from a @tech{world} program. The teachpack provides a mechanism for designating event handlers for servers that is quite similar to the mechanism for describing @tech{world} @@ -897,8 +896,9 @@ This section first introduces some basic forms of data that the @; ----------------------------------------------------------------------------- @subsection{Worlds and Messages} -Understanding the server's event handling functions demands three - concepts. +Understanding the server's event handling functions demands several data + representations: that of (a connection to) a @tech{world} program and that + of a response of a handler to an event. @itemize[ @@ -915,7 +915,7 @@ Understanding the server's event handling functions demands three @defproc[(world=? [u world?][v world?]) boolean?]{ compares two @emph{world}s for equality.} -defproc[(world-name [w world?]) symbol?]{ +@defproc[(world-name [w world?]) symbol?]{ extracts the name from a @emph{world} structure.} @defthing[world1 world?]{a world for testing your programs} @@ -931,9 +931,20 @@ for universe programs. For example: ] } -@item{A @emph{mail} represents a message from an event handler to a -world. The teachpack provides only a predicate and a constructor for these -structures: +@item{Each event handler produces a @emph{bundle}, which is a structure + that contains the list of @emph{world}s to keep track of; the + @tech{server}'s remaining state; and a list of mails to other + worlds: + +@defproc[(bundle? [x any/c]) boolean?]{ + determines whether @scheme[x] is a @emph{bundle}.} + +@defproc[(make-bundle [low (listof world?)] [state any/c] [mails (listof mail?)]) bundle?]{ + creates a @emph{bundle} from a list of worlds, a piece of data that represents a server + state, and a list of mails.} + +A @emph{mail} represents a message from an event handler to a world. The +teachpack provides only a predicate and a constructor for these structures: @defproc[(mail? [x any/c]) boolean?]{ determines whether @scheme[x] is a @emph{mail}.} @@ -942,33 +953,22 @@ structures: creates a @emph{mail} from a @emph{world} and an @tech{S-expression}.} } -@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 -worlds. Again, the teachpack provides only the predicate and a constructor: - -@defproc[(bundle? [x any/c]) boolean?]{ - determines whether @scheme[x] is a @emph{bundle}.} - -@defproc[(make-bundle [listof world?] [state any/c] [mails (listof mail?)]) bundle?]{ - creates a @emph{bundle} from a list of worlds, a piece of data that represents a server - state, and a list of mails.} - -} ] @; ----------------------------------------------------------------------------- @subsection{Universe Descriptions} A @tech{server} keeps track of information about the @tech{universe} that - it manages. Of course, what kind of information it tracks and how it is - represented depends on the situation and the programmer, just as with - @tech{world} programs. + it manages. One kind of tracked information is obviously the collection of + participating world programs, but in general the kind of information that + a server tracks and how the information is represented depends on the + situation and the programmer, just as with @tech{world} programs. -@deftech{UniverseState} @scheme[any/c] represent the server's state For running +@deftech{UniverseState} @scheme[any/c] represents 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 -for the possible states and that your transformation functions are designed +for the possible states and that your event handlers are designed according to the design recipe for this data definition. The @tech{server} itself is created with a description that includes the @@ -996,7 +996,7 @@ registration of new worlds, how it disconnects worlds, how it sends messages from one world to the rest of the registered worlds, and how it renders its current state as a string.} -A @scheme[universe] expression starts a server. Visually it opens +Evaluating a @scheme[universe] expression starts a server. Visually it opens a console window on which you can see that worlds join, which messages are received from which world, and which messages are sent to which world. For convenience, the console also has two buttons: one for shutting down a @@ -1004,8 +1004,8 @@ A @scheme[universe] expression starts a server. Visually it opens especially useful during the integration of the various pieces of a distributed program. -Now it is possible to explain the clauses in a @scheme[universe] server -description. Two of them are mandatory: +The mandatory clauses of a @scheme[universe] server description are +@scheme[on-new] and @scheme[on-msg]: @itemize[ @@ -1015,8 +1015,11 @@ description. Two of them are mandatory: ([new-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? bundle?)])]{ tell DrScheme to call the function @scheme[new-expr] every time another world joins the universe. The event handler is called on the current list of worlds and the - joining world. -}} + joining world, which isn't on the list yet. In particular, the handler may + reject a @tech{world} program from participating in a @tech{universe}, + simply by not including it in the resulting @scheme[bundle] structure. The + handler may still send one message to the world that attempts to join. } +} @item{ @defform[(on-msg msg-expr) @@ -1024,18 +1027,25 @@ description. Two of them are mandatory: ([msg-expr (-> [listof world?] (unsyntax @tech{UniverseState}) world? sexp? bundle?)])]{ tell DrScheme to apply @scheme[msg-expr] to the list of currently - participating worlds, the current state of the universe, the world - that sent the message, and the message itself.} + participating worlds @scheme[low], the current state of the universe, the world + @scheme[w] that sent the message, and the message itself. Note that + @scheme[w] is guaranteed to be on the list @scheme[low]. } -] - 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. +}] + + All proper event handlers produce a @emph{bundle}. The list of worlds in + this @emph{bundle} becomes the server's list of worlds, meaning that only + the server listens only to messages from "approved" 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. -@image["server2.png"] +@; ----------------------------------------------------------------------------- +@;; THE PICTURE IS WRONG +@; ----------------------------------------------------------------------------- + +@image["server.png"] In addition to the mandatory handlers, a program may wish to add some optional handlers: diff --git a/collects/teachpack/world.png b/collects/teachpack/world.png deleted file mode 100644 index 82dd678265d584fc645a40f2b9201fab3e50adb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19925 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 A1^@s6