{"size": 3037, "ext": "scrbl", "max_stars_repo_path": "web-server-doc/web-server/scribblings/web-cells.scrbl", "max_stars_repo_name": "jessealama/web-server", "max_stars_repo_stars_event_min_datetime": "2015-01-21T08:11:58.000Z", "max_stars_repo_stars_event_max_datetime": "2022-03-20T08:28:39.000Z", "max_issues_repo_path": "web-server-doc/web-server/scribblings/web-cells.scrbl", "max_issues_repo_name": "jessealama/web-server", "max_issues_repo_issues_event_min_datetime": "2015-01-14T08:06:37.000Z", "max_issues_repo_issues_event_max_datetime": "2022-02-12T14:38:40.000Z", "max_forks_repo_path": "web-server-doc/web-server/scribblings/web-cells.scrbl", "max_forks_repo_name": "jessealama/web-server", "max_forks_repo_forks_event_min_datetime": "2015-03-05T15:07:36.000Z", "max_forks_repo_forks_event_max_datetime": "2021-07-30T18:59:25.000Z"}
{"max_stars_count": 82, "max_issues_count": 105, "max_forks_count": 37, "avg_line_length": 33.3736263736, "max_line_length": 93, "alphanum_fraction": 0.615409944}
#lang scribble/doc
@(require "web-server.rkt")

@title[#:tag "web-cells"]{Web Cells}
@(require (for-label web-server/http
                     web-server/servlet/web-cells
                     web-server/servlet/web))

@defmodule[web-server/servlet/web-cells]{The
@racketmodname[web-server/servlet/web-cells] library provides the
interface to Web cells.

A Web cell is a kind of state defined relative to the @defterm{frame tree}.
The frame-tree is a mirror of the user's browsing session. Every time a
continuation is invoked, a new frame (called the @defterm{current frame}) is
created as a child of the current frame when the continuation was captured.

You should use Web cells if you want an effect to be encapsulated in all
interactions linked from (in a transitive sense) the HTTP response being
generated. For more information on their semantics, consult the paper 
@href-link["http://www.cs.brown.edu/~sk/Publications/Papers/Published/mk-int-safe-state-web/"
"\"Interaction-Safe State for the Web\""].

@defproc[(web-cell? [v any/c])
         boolean?]{
 Determines if @racket[v] is a web-cell.
}

@defproc[(make-web-cell [v any/c])
         web-cell?]{
 Creates a web-cell with a default value of @racket[v].
}

@defproc[(web-cell-ref [wc web-cell?])
         any/c]{
 Looks up the value of @racket[wc] found in the nearest
 frame.
}

@defproc[(web-cell-shadow [wc web-cell?]
                          [v any/c])
         void]{
 Binds @racket[wc] to @racket[v] in the current frame, shadowing any
 other bindings to @racket[wc] in the current frame.
}
              
Below is an extended example that demonstrates how Web cells allow
the creation of reusable Web abstractions without requiring global
transformations of the program into continuation or store passing style.
@racketmod[
 web-server/insta

 (define (start initial-request)
   (define counter1 (make-counter))
   (define counter2 (make-counter))
   (define include1 (include-counter counter1))
   (define include2 (include-counter counter2))
   (send/suspend/dispatch
    (lambda (embed/url)
      (response/xexpr
       `(html
         (body (h2 "Double Counters")
               (div (h3 "First")
                    ,(include1 embed/url))
               (div (h3 "Second")
                    ,(include2 embed/url))))))))

(define (make-counter)
  (make-web-cell 0))

(define (include-counter a-counter)
  (call-with-current-continuation
   (λ (k)
     (let loop ()
       (k
        (lambda (embed/url)
          `(div (h3 ,(number->string (web-cell-ref a-counter)))
                (a ([href
                     ,(embed/url
                       (lambda _
                         ; A new frame has been created
                         (define last (web-cell-ref a-counter))
                         ; We can inspect the value at the parent
                         (web-cell-shadow a-counter (add1 last))
                         ; The new frame has been modified
                         (loop)))])
                   "+"))))))
   servlet-prompt))
]
}
