{ (define LIBNAME "Simplified Scheme Web Servlets") (include "head.tinc") }

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.


Interface

   ; 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


Pragmatics

The following table specifies what kind of answer each form of query produces:

  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

The functions play the following role:

Example

The following example illustrates how the library enables programs to interact with the consumer. In particular, note the properly recursive calls to login in inform-error. Also note how the primitives make-password and make-number deliver strings and numbers, respectively.

#| 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))
{(include "foot.tinc")}