[plt-scheme] Feature: Expired-continuation response for send/forward, send/finish
This is a good idea and worthy of consideration.
Why don't you alter the web server (it's straightforward), play with
the code for a while, and when you're happy mail it to Greg Pettyjohn
and me as a change request.
-- Matthias
On Nov 21, 2004, at 2:06 PM, Jordan Johnson wrote:
> For list-related administrative tasks:
> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>
> [Warning: half-baked idea follows. May need further baking.]
>
> One thing I find I keep wanting to do is install a
> failure-continuation for when users accidentally reload a form or use
> the back button; it's needlessly frustrating for them to see "The
> transaction referred to...has expired", and I've mostly abandoned use
> of send/forward for that reason, though I like the concept of it.
>
> So, I was thinking, perhaps send/forward could be modified somehow,
> such that when called with one argument it maintains its current
> behavior, but if called with a second procedure, it points all the
> session's defunct k-urls to that procedure as a continuation, rather
> than purging them?
>
> It seems to me that such a continuation might expect a request; or
> perhaps, simply, that it could receive the same k-url generated by
> send/forward for the last valid page, since the only sensible thing to
> do with a request for an expired k-url would be to ignore its
> bindings.
>
> Following is an example of one way it might be used, but first, the
> caveat: I'm not pleased with the way that this example would lead to
> semi-CPS'd code. I know there's got to be a better way to do it.
> Still, I feel a need for a construct that addresses this, and I hope
> my description and example get the point across.
>
> ;;;;;
> ;; not defined here:
> ;; make-question-widget: question-struct -> xexpr
> ;; correct?: question-struct answer -> boolean
> ;; request->answer unpacks an answer from the bindings in a request.
>
> ;; question-struct (req -> void) -> answer
> (define (get-user-answer question bad-user-k)
> (request->answer
> (send/forward
> (lambda (k-url)
> `(html
> (body
> (form ((action ,k-url) (method "POST"))
> ,(make-question-widget question)
> (input ((type "submit") (name "submit") (value
> "submit")))))))
> bad-user-k)))
>
> ;; (listof question-struct) -> void
> (define (quiz-servlet loq)
> (send-start-page)
> (let loop ((questions-left loq)
> (number-answered 0)
> (incorrect '()))
> (if (null? loq)
> (send-end-page answered incorrect)
> (let* ((question (car loq))
> (answer (get-user-answer
> (car loq)
> (lambda (req) ;; here's the new user-error
> continuation
> (send/suspend ;; (which would have to
> escape, yes)
> (lambda (k-url)
> `(html
> (body
> (p "Sorry, you may not go back, only
> "
> (a ((href ,k-url)) "forward")
> ".")))))
> (loop loq number-answered incorrect)))))
> (if (correct? question answer)
> (loop (cdr loq) (add1 number-answered) incorrect)
> (loop (cdr loq)
> (add1 number-answered)
> (cons question incorrect)))))))
>
> ;;;;;
>
> Is there some merit in this? Has it been discussed already? Or is
> there an existing mechanism I could be using instead?
>
> jmj
>
> : Jordan Johnson - jorjohns @ cs . indiana . edu
> : Thrive defensively.
>