racket/collects/teachpack/htdp/scribblings/servlet2.thtml
2008-05-05 02:49:32 +00:00

215 lines
7.4 KiB
Plaintext

{ (define LIBNAME "Simplified Scheme Web Servlets")
(include "head.tinc") }
<p>This teachpack provides a simplified API for PLT Scheme servlets. The
teachpack does not require any understanding of HTML and higher-order
functions. It uses structures and lists, and is therefore well-suited for
use with an HtDP course.
<hr>
<h3>Interface</h3>
<pre>
; Data Constructors -------------------------------------------------------
{(idx make-password)} ; asking for a password
{(idx make-number)} ; asking for a number
{(idx make-yes-no)} ; asking for a Yes-No style answer
{(idx make-boolean)} ; asking for a true-false style answer
{(idx make-radio)} ; requesting one choice from some mutually exclusive choices
#| Data Definitions --------------------------------------------------------
Forms ----------------------------------------------------------------------
Query = (union String
(make-password String)
(make-number String)
(make-boolean String)
(make-yes-no String String String)
(make-radio String (cons String (listof String))))
FormItem = (list Symbol Query)
Form = (cons FormItem (listof FormItem))
Table -------------------------------------------------------------------
Response = (union String Number Boolean)
Table = (listof (list Symbol Response))
|#
; Functions ----------------------------------------------------------------
{(idx form?)} ; TST -> Boolean
; checking the structure of forms
{(idx form-element?)} ; TST -> Boolean
; checking the structure of form-elements
{(idx single-query)} ; Query -> Response
; posing a single question
{(idx queries)} ; (listof Query) -> (listof Response)
; posing a list of questions
{(idx echo-answers)} ; (listof Response) -> true
; echoing the answers from a list of questions to a Web page (development)
{(idx form-query)} ; Form -> Table
; posing a list of questions with tag
{(idx extract/single)} ; Symbol Table -> Response
; extracting the answer for a given tag from a response; the tag must
; occur exactly once.
{(idx extract)} ; Symbol Table -> (listof Response)
; extracting all the answers for a given tag from a response; the list
; is empty if there is no such tag.
{(idx echo-response)} ; Table -> true
; echoing the response from a form to a Web page (development)
{(idx inform)} ; String String *-> true
; posting some information on a Web page, wait for continue signal
{(idx final-page)} ; String String *-> true
; posting some information on a Web page,
; killing the script and all associated backtrack/clone points
</pre>
<hr>
<h3>Pragmatics</h3>
<p>The following table specifies what kind of answer each form of query
produces:
<pre>
Query GUI Item Response
________________________________________________________________________________
String text field String
(make-password String) password field String
(make-number String) text field Number
(make-boolean String) check box Boolean
(make-yes-no String String1 String2) 2-pronged radio String1 or String2
(make-radio String loString) radio button one of loString
(make-button String0) submit button String0
</pre>
<p>The functions play the following role:
<ul>
<li>
<code>form?</code> and <code>form-element?</code> enable programmers to
check the well-formedness of their queries.
<li>
<code>single-query</code> poses a question and waits for a answer from
the consumer.
<li>
<code>queries</code> poses a list of questions and waits for the
submission of answers; it produces a list of answers that is as
long as the list of given questions.
<li>
<code>echo-answers</code> echoes a list of answers to a Web page; this
function is useful for testing Web form designs.
<li>
<code>form-query</code> poses a form with queries and waits for the
submission of answers; it produces a list of tagged or labeled answers
that is as long as the list of given questions.
<li>
<code>echo-response</code> echoes a response to a Web page as a table.
<li>
<code>inform</code> posts some information on a Web page and wait for a
continue signal (a link) from the consumer; the first string plays the
role of a title and the rest form a paragraph.
<li>
<code>final-page</code> posts some information on a Web page and
shuts down the script and all associated backtrack/clone points.
</ul>
<h3>Example</h3>
<p>The following example illustrates how the library enables programs to
interact with the consumer. In particular, note the properly recursive
calls to <code>login</code> in <code>inform-error</code>. Also note how the
primitives <code>make-password</code> and <code>make-number</code> deliver
strings and numbers, respectively.
<pre>
#| Login Site -----------------------------------------------------------------
Author: Matthias Felleisen
Language: Intermediate
Teachpack: servlet2.ss
Login Web Site:
A login site consists of three pages:
1. login: request user information: name, password, year-of-birth
- if correct, respond with greeting for name
- if incorrect, go to error page
2. error: inform user of error, continue goes back to login page
3. greetings: say hello to name
The second and third are generated from user input, the first is
generated by the program alone.
|#
;; Login Page -----------------------------------------------------------------
; ask three questions: one plain, one password, one numeric
(define login-page
(list
(list 'name "User Name")
(list 'pass (make-password "Password"))
(list 'yofb (make-number "Year-of-birth"))))
; Table -> true
; process the response for login-page
(define (login r)
(let ([name (extract/single 'name r)])
(if (string=? (lookup-password name) (extract/single 'pass r))
(if (= (lookup-yofb name) (extract/single 'yofb r))
(greetings name)
(inform-error "bad data"))
(inform-error "bad match"))))
; String -> (union false String)
; lookup the password for name in DB
(define (lookup-password name)
(local ([define (x=? x) (string=? name x)]
[define r (assf x=? DB)])
(if (boolean? r) false (second r))))
; String -> (union false Number)
; lookup the year-of-birth for name in DB
(define (lookup-yofb name)
(local ([define (x=? x) (string=? name x)]
[define r (assf x=? DB)])
(if (boolean? r) false (third r))))
(define DB
'(("matthias" "okay" 1958)))
;; Error Page -----------------------------------------------------------------
; String -> true
; consume error message, print and enable return to login page
(define (inform-error s)
(let ([_ (inform "Error" s)])
(login (form-query login-page))))
;; Greetings Page -------------------------------------------------------------
; String -> true
; consume name and display good bye message
(define (greetings name)
(inform "Welcome" "Welcome " name " and good bye."))
;; RUN ------------------------------------------------------------------------
(login (form-query login-page))
</pre>
{(include "foot.tinc")}