#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)) ] }