了解 Racket Web 框架中的 send/suspend/dispatch

Understanding send/suspend/dispatch in Racket Web Framework

我正在尝试理解与 Racket Web 框架教程 http://docs.racket-lang.org/continue/ 中的 send/suspend/dispatch 代码相关的示例。

这里是让我困惑的代码:

#lang web-server/insta
; start: request -> response
   (define (start request)
      (show-counter 0 request))

; show-counter: number request -> doesn't return
; Displays a number that's hyperlinked: when the link is pressed,
; returns a new page with the incremented number.
(define (show-counter n request)
  (local [(define (response-generator embed/url)
            (response/xexpr
             `(html (head (title "Counting example"))
                    (body
                     (a ((href ,(embed/url next-number-handler)))
                        ,(number->string n))))))

          (define (next-number-handler request)
            (show-counter (+ n 1) request))]

    (send/suspend/dispatch response-generator)))

我有两个问题:

(最重要)embed/url是在哪里定义的?我看不到它是在此代码中定义的,但我对延续的理解是基本的,所以我可能遗漏了一些东西。

本地的目的是什么?我可以删除它,代码似乎也能正常工作。

函数embed/url是响应生成器的参数:

(define (response-generator embed/url) ...)

计算 (send/suspend/dispatch response-generator) 时,会发生以下情况:

1. a procedure `p` given a "continuation" (here next-number-handler)" 
   generates an url
2. the function `response-generator` is called with `p` as argument.
3. the page `(html ... ,(embed-url next-number-handler)) is generated
   (note: (embed-url next-number-handler) calls `p` and the resulting url is inserted into the page)

4. [send]     the page is sent to the client
5. [suspend]  the server suspends the program
6. [dispatch] receives an request generated by clicking link whose url were
              generated in 3.  The handler associated to the url 
              (here next-number-handler) is looked up, and the handler 
              is called.

虽然没有必要使用 send/suspend/dispatch 这里有一个草图:

(define (send/suspend/dispatch response-generator )
  (let/ec escape
    (define (callback->url callback)
      (let/ec return-url
        (escape (callback (send/suspend return-url)))))
    (send/back (response-generator callback->url))))