[plt-scheme] send/suspend return values
On Nov 21, 2004, at 4:17 PM, Matthias Felleisen wrote:
> No. When you can (send/suspend f), send/suspend does not invoke f in
> tail-position. Instead it names the result and makes sure it is a
> response. I have to admit that after looking at the code I find it way
> too defensive. The author should have instead stated the contract of
> send/suspend as
>
> (String -> X) -> X
>
> which would then allow f to return multiple values.
You're proposed contract for send/suspend would break the web-server.
It needs to be: (string -> response) -> request
The web-server doesn't know how to make a response out of an arbitrary
X and
the continuation of send/suspend needs to get a request.
A multi-valued send/suspend would have a contract like this:
(string -> response . X) -> request . X
I.e. the first of multiple values returned *to* send/suspend would be
a response and the first of multiple values returned *from* send/suspend
would be a request.
This is an interesting idea, because it allows the servlet writer to
close the continuation
over the extra values.
Here's my take on the proposed pattern:
;; ****************************************
;; EXAMPLE 1
;; form-gen: X -> string -> request
;; generate a response generator
(define (form-gen . data)
(lambda (url)
F(url, data)))
;; client code for form-gen
(let ([request (send/suspend (form-gen some-data))])
G(request, data))
;; ****************************************
;; EXAMPLE 2
;; form-and-data-gen: (-> (string -> request) . X)
;; generate a response generator and the data it is closed over
(define (form-and-data-gen)
(let ([data ...])
(values
(lambda (url) F(data))
data)))
;; client code
(let-values ([(make-form data) (form-and-data-gen)])
G((send/suspend make-form) data))
;; ****************************************
;; EXAMPLE 3 (using proposed multi-valued send/suspend)
;; form-and-data: (string -> response . X)
;; generate a response and the data it is closed over
(define (form-and-data url)
(let ([data ...])
(values
`(html ... ,url ...)
data)))
;; client-code
(let-values ([(request data) (send/suspend form-and-data)])
G(request data))
;; ****************************************
;; EXAMPLE 4 (using send/suspend/dispatch)
(let ([data ...])
(send/suspend/dispatch
`(html ... ,(embed-procedure (lambda (request) G(request, data))))))
If I understand the pattern correctly, I think we've already got it
covered
thanks to Pete Hopkins.