Lots of documentation formatting.

Started as fixing misindented definitions, then more indentations, then
a bunch of similar things (square brackets, huge spaces at end-of-lines,
etc).
This commit is contained in:
Eli Barzilay 2011-08-15 07:50:04 -04:00
parent d3d9514b1c
commit d61eb53686
113 changed files with 1081 additions and 923 deletions

View File

@ -8,7 +8,8 @@
(require (for-label racket/serialize))
(define id (racket define-serializable-struct))
(define id2 (racket define-serializable-struct/versions))))
(bind racket-define-serializable-struct racket-define-serializable-struct/versions))
(bind racket-define-serializable-struct
racket-define-serializable-struct/versions))
@mzlib[#:mode title serialize]

View File

@ -110,11 +110,11 @@ Raised for errors when handling cookies.}
@subsection{Creating a cookie}
@racketblock[
(let ((c (cookie:add-max-age
(let ([c (cookie:add-max-age
(cookie:add-path
(set-cookie "foo" "bar")
"/servlets")
3600)))
3600)])
(print-cookie c))
]

View File

@ -199,8 +199,8 @@ the bounds of the image, returns a transparent color.}
[f (-> natural-number/c natural-number/c color?)])
image?]{
Builds an image of the specified size and shape by calling the specified function
on the coordinates of each pixel. For example,
Builds an image of the specified size and shape by calling the specified
function on the coordinates of each pixel. For example,
@codeblock|{
; fuzz : image -> image
(define (fuzz pic)

View File

@ -229,7 +229,6 @@ The @racket[pkg] argument must end with @racket[".plt"].
}
@defproc[(get-package-spec [owner string?]
[pkg (and/c string? #rx"[.]plt$")]
[maj (or/c #f natural-number/c) #f]
@ -284,7 +283,8 @@ See also @racket[build-scribble-docs?] and @racket[force-package-building?]
}
@defparam[force-package-building? b boolean?]{
Determines if @racket[make-planet-archive] is more strict and thus aborts more often.
Determines if @racket[make-planet-archive] is more strict and thus
aborts more often.
}
@defproc[(download-package [pkg-spec pkg-spec?])
@ -418,7 +418,8 @@ produces a list corresponding to its name and version, exactly like
}
@defproc[(pkg? [v any/c]) boolean?]{
Determines if its argument is a pkg, the representation of an installed package.
Determines if its argument is a pkg, the representation of an
installed package.
}
@section[#:tag "version.rkt"]{Package Version}

View File

@ -181,15 +181,15 @@ function, we could do the following:
#:segments [segments 20]
#:color [color 'red]
#:width [width 1])
(let* ((dash-size (/ (- x-max x-min) segments))
(x-lists (build-list
(let* ([dash-size (/ (- x-max x-min) segments)]
[x-lists (build-list
(/ segments 2)
(lambda (index)
(x-values
(/ samples segments)
(+ x-min (* 2 index dash-size))
(+ x-min (* (add1 (* 2 index))
dash-size)))))))
dash-size)))))])
(lambda (2dview)
(send 2dview set-line-color color)
(send 2dview set-line-width width)

View File

@ -399,7 +399,7 @@ Dispatching-related bindings:
@racketblock[
(define (ttref)
(let ((url (get-arg)) (text (get-arg)))
(let ([url (get-arg)] [text (get-arg)])
(list "<a href=\"" url "\">@tt{" text "}</a>")))
]

View File

@ -76,7 +76,7 @@ cases. Here's a simple test case written using the
@racketblock[
(test-begin
(let ((lst (list 2 4 6 9)))
(let ([lst (list 2 4 6 9)])
(check = (length lst) 4)
(for-each
(lambda (elt)
@ -111,7 +111,7 @@ we're testing. We can give a test case a name with the
@racketblock[
(test-case
"List has length 4 and all elements even"
(let ((lst (list 2 4 6 9)))
(let ([lst (list 2 4 6 9)])
(check = (length lst) 4)
(for-each
(lambda (elt)
@ -133,7 +133,7 @@ group them into a test suite:
(test-case
"List has length 4 and all elements even"
(let ((lst (list 2 4 6 9)))
(let ([lst (list 2 4 6 9)])
(check = (length lst) 4)
(for-each
(lambda (elt)

View File

@ -62,7 +62,7 @@ racket
(r (f lov)
(lambda (r)
(define f@r (f r))
(for/and ((v lov)) (>= f@r (f v))))))])
(for/and ([v lov]) (>= f@r (f v))))))])
]
It is a @emph{dependent} contract that names the two arguments and uses
the names to impose a predicate on the result. This predicate computes
@ -84,9 +84,8 @@ racket
(r (f lov)
(lambda (r)
(define f@r (f r))
(and
(memq r lov)
(for/and ((v lov)) (>= f@r (f v)))))))])
(and (memq r lov)
(for/and ([v lov]) (>= f@r (f v)))))))])
]
The @racket[memq] function ensures that @racket[r] is @emph{intensionally equal}
@margin-note*{That is, "pointer equality" for those who prefer to think at
@ -113,7 +112,7 @@ racket
(r (f lov)
(lambda (r)
(define f@r (f r))
(and (for/and ((v lov)) (>= f@r (f v)))
(and (for/and ([v lov]) (>= f@r (f v)))
(eq? (first (memf (lambda (v) (= (f v) f@r)) lov))
r)))))])
]
@ -157,7 +156,7 @@ racket
@code:comment{@#,dominates1}
(define (dominates-all f@r f lov)
(for/and ((v lov)) (>= (f v) f@r)))
(for/and ([v lov]) (>= (f v) f@r)))
@code:comment{@#,first?1}
(define (is-first-max? r f@r f lov)
@ -199,7 +198,7 @@ racket
@code:comment{@#,dominates2}
(define (dominates-all f@r flov)
(for/and ((f@v flov)) (>= f@r f@v)))
(for/and ([f@v flov]) (>= f@r f@v)))
@code:comment{@#,first?2}
(define (is-first-max? r f@r lov+flov)

View File

@ -82,8 +82,7 @@ streams like this:
#:eval e
(define stream/c
(promise/c
(or/c
null?
(or/c null?
(cons/c number? stream/c))))
]
@close-eval[e]
@ -99,8 +98,7 @@ Instead, use
(promise/c
(or/c
null?
(cons/c 1
(recursive-contract stream/c)))))
(cons/c 1 (recursive-contract stream/c)))))
]
The use of @racket[recursive-contract] delays the evaluation of the

View File

@ -261,7 +261,7 @@ resulting iteration can be performed more efficiently than plain
@racket[for/vector] or @racket[for*/vector]:
@interaction[
(let ((chapters '("Intro" "Details" "Conclusion")))
(let ([chapters '("Intro" "Details" "Conclusion")])
(for/vector #:length (length chapters) ([i (in-naturals 1)]
[chapter chapters])
(string-append (number->string i) ". " chapter)))

View File

@ -64,18 +64,18 @@ Consider the following core of a Mandelbrot-set computation:
@racketblock[
(define (mandelbrot iterations x y n)
(let ((ci (- (/ (* 2.0 y) n) 1.0))
(cr (- (/ (* 2.0 x) n) 1.5)))
(let loop ((i 0) (zr 0.0) (zi 0.0))
(let ([ci (- (/ (* 2.0 y) n) 1.0)]
[cr (- (/ (* 2.0 x) n) 1.5)])
(let loop ([i 0] [zr 0.0] [zi 0.0])
(if (> i iterations)
i
(let ((zrq (* zr zr))
(ziq (* zi zi)))
(let ([zrq (* zr zr)]
[ziq (* zi zi)])
(cond
((> (+ zrq ziq) 4.0) i)
(else (loop (add1 i)
[(> (+ zrq ziq) 4.0) i]
[else (loop (add1 i)
(+ (- zrq ziq) cr)
(+ (* 2.0 zr zi) ci)))))))))
(+ (* 2.0 zr zi) ci))]))))))
]
The expressions @racket[(mandelbrot 10000000 62 500 1000)] and
@ -110,8 +110,8 @@ first the problem:
@racketblock[
(define (mandelbrot iterations x y n)
(let ((ci (- (/ (* 2.0 (->fl y)) (->fl n)) 1.0))
(cr (- (/ (* 2.0 (->fl x)) (->fl n)) 1.5)))
(let ([ci (- (/ (* 2.0 (->fl y)) (->fl n)) 1.0)]
[cr (- (/ (* 2.0 (->fl x)) (->fl n)) 1.5)])
....))
]
@ -128,18 +128,18 @@ much less allocation:
@racketblock[
(define (mandelbrot iterations x y n)
(let ((ci (fl- (fl/ (* 2.0 (->fl y)) (->fl n)) 1.0))
(cr (fl- (fl/ (* 2.0 (->fl x)) (->fl n)) 1.5)))
(let loop ((i 0) (zr 0.0) (zi 0.0))
(let ([ci (fl- (fl/ (* 2.0 (->fl y)) (->fl n)) 1.0)]
[cr (fl- (fl/ (* 2.0 (->fl x)) (->fl n)) 1.5)])
(let loop ([i 0] [zr 0.0] [zi 0.0])
(if (> i iterations)
i
(let ((zrq (fl* zr zr))
(ziq (fl* zi zi)))
(let ([zrq (fl* zr zr)]
[ziq (fl* zi zi)])
(cond
((fl> (fl+ zrq ziq) 4.0) i)
(else (loop (add1 i)
[(fl> (fl+ zrq ziq) 4.0) i]
[else (loop (add1 i)
(fl+ (fl- zrq ziq) cr)
(fl+ (fl* 2.0 (fl* zr zi)) ci)))))))))
(fl+ (fl* 2.0 (fl* zr zi)) ci))]))))))
]
This conversion can speed @racket[mandelbrot] by a factor of 8, even

View File

@ -280,7 +280,8 @@ For communication among @tech{places}, the new byte string is allocated in the
the other operations.
@examples[
(define b
(bytes->string/utf-8 (bytes #xc3 #xa7 #xc3 #xb0 #xc3 #xb6 #xc2 #xa3)))
(bytes->string/utf-8
(bytes #xc3 #xa7 #xc3 #xb0 #xc3 #xb6 #xc2 #xa3)))
(string->bytes/utf-8 b)
(bytes->string/utf-8 (string->bytes/utf-8 b))

View File

@ -292,13 +292,13 @@ interface @racket[(class->interface object%)], and is transparent
(lambda kw-formals expr ...+)
(case-lambda (formals expr ...+) ...)
(#%plain-lambda formals expr ...+)
(let-values (((id) method-procedure) ...)
(let-values ([(id) method-procedure] ...)
method-procedure)
(letrec-values (((id) method-procedure) ...)
(letrec-values ([(id) method-procedure] ...)
method-procedure)
(let-values (((id) method-procedure) ...+)
(let-values ([(id) method-procedure] ...+)
id)
(letrec-values (((id) method-procedure) ...+)
(letrec-values ([(id) method-procedure] ...+)
id)])]{
Produces a class value.

View File

@ -196,4 +196,3 @@ For communication among @tech{places}, the new @tech{fxvector} is
allocated in the @tech{shared memory space}.
@mz-examples[#:eval flfx-eval (make-shared-fxvector 4 3)]}

View File

@ -481,7 +481,8 @@ instead of @racket[match].}
type named @racket[struct-id], where the field @racket[field] in the
instance matches the corresponding @racket[pat].
Any field of @racket[struct-id] may be omitted, and such fields can occur in any order.
Any field of @racket[struct-id] may be omitted, and such fields can
occur in any order.
@defexamples[
#:eval match-eval

View File

@ -44,7 +44,7 @@ new parameter value. A guard procedure can raise an exception to
reject a change to the parameter's value. The @racket[guard] is not
applied to the initial @racket[v].}
@defform[(parameterize ((parameter-expr value-expr) ...)
@defform[(parameterize ([parameter-expr value-expr] ...)
body ...+)
#:contracts
([parameter-expr parameter?])]{

View File

@ -24,7 +24,7 @@ used as a macro that expands to a use of the target identifier, but
@racket[syntax-local-value] of @racket[id] does not produce
the target's value.}
@defform[(syntax-parameterize ((id expr) ...) body-expr ...+)]{
@defform[(syntax-parameterize ([id expr] ...) body-expr ...+)]{
@margin-note/ref{See also @racket[splicing-syntax-parameterize].}

View File

@ -139,7 +139,7 @@ For example, the expression
expands to
@racketblock[
(let ((or-part x)) (if or-part or-part (or y)))
(let ([or-part x]) (if or-part or-part (or y)))
]
which, in turn, expands to

View File

@ -210,9 +210,9 @@ the binding (according to @racket[free-identifier=?]) matters.}
(if expr expr expr)
(begin expr ...+)
(begin0 expr expr ...)
(let-values (((id ...) expr) ...)
(let-values ([(id ...) expr] ...)
expr ...+)
(letrec-values (((id ...) expr) ...)
(letrec-values ([(id ...) expr] ...)
expr ...+)
(set! id expr)
(@#,racket[quote] datum)

View File

@ -109,7 +109,7 @@ is prefixed with the special form name as described under
@examples[#:eval the-eval
(wrong-syntax #'here "expected ~s" 'there)
(parameterize ((current-syntax-context #'(look over here)))
(parameterize ([current-syntax-context #'(look over here)])
(wrong-syntax #'here "expected ~s" 'there))
]
@ -117,7 +117,7 @@ A macro using @racket[wrong-syntax] might set the syntax context at the very
beginning of its transformation as follows:
@RACKETBLOCK[
(define-syntax (my-macro stx)
(parameterize ((current-syntax-context stx))
(parameterize ([current-syntax-context stx])
(syntax-case stx ()
___)))
]

View File

@ -117,8 +117,8 @@ form.}
(->d (arg ...) () #:rest id rest [id result])])]{
Like @racket[proc-doc], but supporting contract forms that embed
argument names. Only a subset of @racket[->i] and @racket[->d] forms are currently
supported.}
argument names. Only a subset of @racket[->i] and @racket[->d] forms are
currently supported.}
@defform[(thing-doc id contract-expr dec-expr)]{

View File

@ -163,7 +163,6 @@ Transfers cross-reference information to @racket[ci], which is the
initially collected information from @racket[renderer].}
@defproc[(xref-index [xref xref?]) (listof entry?)]{
Converts indexing information @racket[xref] into a list of

View File

@ -83,12 +83,12 @@ language [*]:
"#<procedure:closure-storing-proc>"
(#%plain-lambda (x)
(begin
(let-values (((arg0-1643 arg1-1644 arg2-1645)
(let-values ([(arg0-1643 arg1-1644 arg2-1645)
(#%plain-app
values
"#<*unevaluated-struct*>"
"#<*unevaluated-struct*>"
"#<*unevaluated-struct*>")))
"#<*unevaluated-struct*>")])
(with-continuation-mark "#<debug-key-struct>"
(#%plain-lambda ()
(#%plain-app
@ -161,7 +161,7 @@ language [*]:
#f
(#%plain-lambda () (#%plain-app list f))))))))
(let-values (((done-already?) (quote #f)))
(let-values ([(done-already?) (quote #f)])
(#%app dynamic-wind void
(lambda () (#%app dynamic-require (quote (quote #%htdp)) (quote #f)))
(lambda () (if done-already?

View File

@ -11,8 +11,8 @@
@(begin
(define the-eval
(parameterize ((sandbox-output 'string)
(sandbox-error-output 'string))
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string])
(make-evaluator 'racket/base #:requires '(syntax/keyword))))
;;(void (the-eval '(error-print-source-location #f)))
(define-syntax-rule (myexamples e ...)

View File

@ -23,11 +23,11 @@ the parameter expressions.
[(_ ((p v:expr) ...) body:expr)
#:declare p (expr/c #'parameter?
#:name "parameter argument")
#'(parameterize ((p.c v) ...) body)]))
(myparameterize ((current-input-port
(open-input-string "(1 2 3)")))
#'(parameterize ([p.c v] ...) body)]))
(myparameterize ([current-input-port
(open-input-string "(1 2 3)")])
(read))
(myparameterize (('whoops 'something))
(myparameterize (['whoops 'something])
'whatever)
]

View File

@ -425,7 +425,6 @@ They all construct a triangle oriented as follows:
}
@defproc*[([(square [side-len (and/c real? (not/c negative?))]
[mode mode?]
[color image-color?])
@ -657,7 +656,6 @@ the @racket[point-count] argument determines how many points the star has.
(rectangle 40 40 "solid" "silver")
(rectangle 50 50 "solid" "seagreen"))]
}
@defproc[(overlay/offset [i1 image?] [x real?] [y real?] [i2 image?]) image?]{
@ -777,7 +775,6 @@ the @racket[point-count] argument determines how many points the star has.
(rectangle 30 30 50 "seagreen")
(rectangle 20 20 50 "seagreen"))]
}
@ -869,7 +866,6 @@ the @racket[point-count] argument determines how many points the star has.
(ellipse 20 30 "solid" "dimgray")
(ellipse 20 10 "solid" "black"))]
}
@defproc[(beside/align [y-place y-place?] [i1 image?] [i2 image?] [is image?] ...) image?]{
@ -894,7 +890,6 @@ the @racket[point-count] argument determines how many points the star has.
(text "ijy" 18 "black")
(text "ijy" 24 "black"))]
}
@ -907,7 +902,6 @@ the @racket[point-count] argument determines how many points the star has.
(ellipse 30 20 "solid" "dimgray")
(ellipse 10 20 "solid" "black"))]
}
@defproc[(above/align [x-place x-place?] [i1 image?] [i2 image?] [is image?] ...) image?]{
@ -928,7 +922,6 @@ the @racket[point-count] argument determines how many points the star has.
(ellipse 30 20 "solid" "darkolivegreen")
(ellipse 10 20 "solid" "darkgreen"))]
}
@section{Placing Images & Scenes}
@ -1201,9 +1194,10 @@ more expensive than with the other shapes.
([bitmap-spec rel-string
id])]{
Loads the bitmap specified by @racket[bitmap-spec]. If @racket[bitmap-spec] is a string, it is treated as a
relative path. If it is an identifier, it is treated like a require spec and used to refer to a file
in a collection.
Loads the bitmap specified by @racket[bitmap-spec]. If
@racket[bitmap-spec] is a string, it is treated as a relative path.
If it is an identifier, it is treated like a require spec and used to
refer to a file in a collection.
@image-examples[(bitmap icons/stop-16x16.png)
(bitmap icons/b-run.png)]

View File

@ -34,8 +34,7 @@ Example:
(view dir)
(printf "~a ~n" (control)))))
(connect
(make-model "left")
(connect (make-model "left")
(make-model "right")
(make-model "up")
(make-model "down"))

View File

@ -34,15 +34,20 @@ This module provides a macro for regular expression compilation.
pat])]{
Compiles a regular expression over match patterns to a @racket[machine].
The interpretation of the pattern language is mostly intuitive. The pattern language may be extended
with @racket[define-re-transformer]. @racket[dseq] allows bindings of the @racket[match] pattern to be
used in the rest of the regular expression. (Thus, they are not @emph{really} regular expressions.)
@racket[unquote] escapes to Racket to evaluate an expression that evaluates to a regular expression (this happens
once, at compile time.) @racket[rec] binds a Racket identifier to a delayed version of the inner expression; even
if the expression is initially accepting, this delayed version is never accepting.
The interpretation of the pattern language is mostly intuitive. The
pattern language may be extended with @racket[define-re-transformer].
@racket[dseq] allows bindings of the @racket[match] pattern to be used
in the rest of the regular expression. (Thus, they are not
@emph{really} regular expressions.) @racket[unquote] escapes to Racket
to evaluate an expression that evaluates to a regular expression (this
happens once, at compile time.) @racket[rec] binds a Racket identifier
to a delayed version of the inner expression; even if the expression is
initially accepting, this delayed version is never accepting.
The compiler will use an NFA, provided @racket[complement] and @racket[dseq] are not used. Otherwise,
many NFAs connected with the machine simulation functions from @racketmodname[unstable/automata/machine] are used.
The compiler will use an NFA, provided @racket[complement] and
@racket[dseq] are not used. Otherwise, many NFAs connected with the
machine simulation functions from
@racketmodname[unstable/automata/machine] are used.
}
@(define-syntax-rule (defidforms (id ...) . dat)

View File

@ -24,18 +24,26 @@
[name? identifier?]
[method identifier?])]{
Defines @racket[name] as a transformer binding for the static information about a new generic group.
Defines @racket[name] as a transformer binding for the static
information about a new generic group.
Defines @racket[prop:name] as a structure
type property. Structure types implementing this generic group should have this property where the value is a vector
with one element per @racket[method] where each value is
either @racket[#f] or a procedure with the same arity as specified by @racket[kw-formals*].
(@racket[kw-formals*] is similar to the @racket[kw-formals] used by @racket[lambda], except no expression is given for optional arguments.)
The arity of each method is checked by the guard on the structure type property.
Defines @racket[prop:name] as a structure type property. Structure
types implementing this generic group should have this property where
the value is a vector with one element per @racket[method] where each
value is either @racket[#f] or a procedure with the same arity as
specified by @racket[kw-formals*]. (@racket[kw-formals*] is similar to
the @racket[kw-formals] used by @racket[lambda], except no expression is
given for optional arguments.) The arity of each method is checked by
the guard on the structure type property.
Defines @racket[name?] as a predicate identifying instances of structure types that implement this generic group.
Defines @racket[name?] as a predicate identifying instances of structure
types that implement this generic group.
Defines each @racket[method] as a generic procedure that calls the corresponding method on values where @racket[name?] is true. Each method must have a required by-position argument that is @racket[free-identifier=?] to @racket[name]. This argument is used in the generic definition to locate the specialization.
Defines each @racket[method] as a generic procedure that calls the
corresponding method on values where @racket[name?] is true. Each method
must have a required by-position argument that is
@racket[free-identifier=?] to @racket[name]. This argument is used in
the generic definition to locate the specialization.
}
@ -61,13 +69,18 @@ context of @racket[name].
#:contracts
([name identifier?])]{
@racket[name] must be a transformer binding for the static information about a new generic group.
@racket[name] must be a transformer binding for the static information
about a new generic group.
Expands to a value usable as the property value for the structure type property of the @racket[name] generic group.
Expands to a value usable as the property value for the structure type
property of the @racket[name] generic group.
If the @racket[definition]s define the methods of @racket[name], then they are used in the property value.
If the @racket[definition]s define the methods of @racket[name], then
they are used in the property value.
If any method of @racket[name] is not defined, then @racket[#f] is used to signify that the structure type does not implement the particular method.
If any method of @racket[name] is not defined, then @racket[#f] is used
to signify that the structure type does not implement the particular
method.
Allows @racket[define/generic] to appear in @racket[definition ...].
@ -78,7 +91,9 @@ Allows @racket[define/generic] to appear in @racket[definition ...].
([local-name identifier?]
[method-name identifier?])]{
When used inside @racket[define-methods], binds @racket[local-name] to the generic for @racket[method-name]. This is useful for method specializations to use the generic methods on other values.
When used inside @racket[define-methods], binds @racket[local-name] to
the generic for @racket[method-name]. This is useful for method
specializations to use the generic methods on other values.
Syntactically an error when used outside @racket[define-methods].

View File

@ -29,9 +29,18 @@ This library provides a simplified version of parameters that are backed by cont
[none-v [any/c #f]]
[tag continuation-prompt-tag? default-continuation-prompt-tag])
(listof vector?)]{
Returns the values of the @racket[mps] up to @racket[tag]. The length of each vector in the result list is the same as the length of @racket[mps], and a value in a particular vector position is the value for the corresponding mark parameter in @racket[mps]. Values for multiple mark parameter appear in a single vector only when the mark parameters are for the same continuation frame in the current continuation. The @racket[none-v] argument is used for vector elements to indicate the lack of a value.
Returns the values of the @racket[mps] up to @racket[tag]. The length
of each vector in the result list is the same as the length of
@racket[mps], and a value in a particular vector position is the value
for the corresponding mark parameter in @racket[mps]. Values for
multiple mark parameter appear in a single vector only when the mark
parameters are for the same continuation frame in the current
continuation. The @racket[none-v] argument is used for vector elements
to indicate the lack of a value.
}
@defform[(mark-parameterize ([mp expr] ...) body-expr ...)]{
Parameterizes @racket[(begin body-expr ...)] by associating each @racket[mp] with the evaluation of @racket[expr] in the parameterization of the entire expression.
Parameterizes @racket[(begin body-expr ...)] by associating each
@racket[mp] with the evaluation of @racket[expr] in the
parameterization of the entire expression.
}

View File

@ -40,16 +40,16 @@ The other arguments have the same meaning as for @racket[expr/c].
@examples[#:eval the-eval
(define-syntax (myparameterize1 stx)
(syntax-case stx ()
[(_ ((p v)) body)
[(_ ([p v]) body)
(with-syntax ([cp (wrap-expr/c
#'parameter? #'p
#:name "the parameter argument"
#:context stx)])
#'(parameterize ((cp v)) body))]))
(myparameterize1 ((current-input-port
(open-input-string "(1 2 3)")))
#'(parameterize ([cp v]) body))]))
(myparameterize1 ([current-input-port
(open-input-string "(1 2 3)")])
(read))
(myparameterize1 (('whoops 'something))
(myparameterize1 (['whoops 'something])
'whatever)
(module mod racket

View File

@ -7,8 +7,8 @@
web-server/lang/serial-lambda
web-server/private/define-closure))
The defunctionalization process of the Web Language (see @secref["stateless" #:doc '(lib "web-server/scribblings/web-server.scrbl")])
The defunctionalization process of the Web Language (see
@secref["stateless" #:doc '(lib "web-server/scribblings/web-server.scrbl")])
requires an explicit representation of closures that is serializable.
@defmodule[web-server/lang/serial-lambda]{
@ -18,7 +18,8 @@ requires an explicit representation of closures that is serializable.
}
@defform[(serial-case-lambda [formals body ...] ...)]{
Returns @racket[(case-lambda [formals body ...] ...)], except it is serializable.
Returns @racket[(case-lambda [formals body ...] ...)], except it is
serializable.
}
}

View File

@ -20,9 +20,10 @@
[path->serlvet path->servlet/c])
(values (-> void)
url->servlet/c)]{
The first return value flushes the cache.
The second is a procedure that uses @racket[url->path] to resolve the URL to a path, then uses @racket[path->servlet] to resolve
that path to a servlet, caching the results in an internal table.
The first return value flushes the cache. The second is a procedure
that uses @racket[url->path] to resolve the URL to a path, then uses
@racket[path->servlet] to resolve that path to a servlet, caching the
results in an internal table.
}
@defproc[(make [url->servlet url->servlet/c]
@ -35,9 +36,12 @@
(url? exn? . -> . can-be-response?)
servlet-error-responder])
dispatcher/c]{
This dispatcher runs racket servlets, using @racket[url->servlet] to resolve URLs to the underlying servlets.
If servlets have errors loading, then @racket[responders-servlet-loading] is used. Other errors are handled with
@racket[responders-servlet]. If a servlet raises calls @racket[next-dispatcher], then the signal is propagated by this dispatcher.
This dispatcher runs racket servlets, using @racket[url->servlet] to
resolve URLs to the underlying servlets. If servlets have errors
loading, then @racket[responders-servlet-loading] is used. Other errors
are handled with @racket[responders-servlet]. If a servlet raises calls
@racket[next-dispatcher], then the signal is propagated by this
dispatcher.
}
}

View File

@ -102,10 +102,12 @@ URLs to paths on the filesystem.
@defproc[(filter-url->path [regex regexp?]
[url->path url->path/c])
url->path/c]{
Runs the underlying @racket[url->path] but will only return if the path, when considered as a string,
matches the @racket[regex]. This is useful to disallow strange files, like GIFs, from being considered
servlets when using the servlet dispatchers. It will return a @racket[exn:fail:filesystem:exists?] exception if
the path does not match.
Runs the underlying @racket[url->path] but will only return if the
path, when considered as a string, matches the @racket[regex]. This is
useful to disallow strange files, like GIFs, from being considered
servlets when using the servlet dispatchers. It will return a
@racket[exn:fail:filesystem:exists?] exception if the path does not
match.
}
}
@ -249,9 +251,9 @@ a URL that refreshes the password file, servlet cache, etc.}
web-server/configuration/responders))
@defthing[denied?/c contract?]{
Equivalent to @racket[(request? . -> . (or/c false/c string?))].
The return is the authentication realm as a string if the request is not authorized and
@racket[#f] if the request @emph{is} authorized.
Equivalent to @racket[(request? . -> . (or/c false/c string?))]. The
return is the authentication realm as a string if the request is not
authorized and @racket[#f] if the request @emph{is} authorized.
}
@defproc[(make [denied? denied?/c]
@ -260,24 +262,26 @@ a URL that refreshes the password file, servlet cache, etc.}
(url? header? . -> . response?)
(gen-authentication-responder "forbidden.html")])
dispatcher/c]{
A dispatcher that checks if the request is denied based on @racket[denied?]. If so, then
@racket[authentication-responder] is called with a @racket[header] that
requests credentials. If not, then @racket[next-dispatcher] is
invoked.
A dispatcher that checks if the request is denied based on
@racket[denied?]. If so, then @racket[authentication-responder] is
called with a @racket[header] that requests credentials. If not, then
@racket[next-dispatcher] is invoked.
}
@defthing[authorized?/c contract?]{
Equivalent to @racket[(string? (or/c false/c bytes?) (or/c false/c bytes?) . -> . (or/c false/c string?))].
The input is the URI as a string and the username and passwords as bytes.
The return is the authentication realm as a string if the user is not authorized and
@racket[#f] if the request @emph{is} authorized.
Equivalent to
@racket[(string? (or/c false/c bytes?) (or/c false/c bytes?) . -> . (or/c false/c string?))].
The input is the URI as a string and the username and passwords as
bytes. The return is the authentication realm as a string if the user
is not authorized and @racket[#f] if the request @emph{is} authorized.
}
@defproc[(make-basic-denied?/path [password-file path-string?])
(values (-> void)
authorized?/c)]{
Creates an authorization procedure based on the given password file. The first returned value
is a procedure that refreshes the password cache used by the authorization procedure.
Creates an authorization procedure based on the given password
file. The first returned value is a procedure that refreshes the
password cache used by the authorization procedure.
@racket[password-file] is parsed as:
@racketblock[(list ([domain : string?]

View File

@ -23,8 +23,7 @@ Suppose we want to create an abstraction of entering a date in an HTML form. The
@racketblock[
(define date-formlet
(formlet
(div
"Month:" ,{input-int . => . month}
(div "Month:" ,{input-int . => . month}
"Day:" ,{input-int . => . day})
(list month day)))
]
@ -233,7 +232,8 @@ types. Refer to @secref["input-formlets"] for example low-level formlets using t
@defproc[(xml-forest [r xexpr-forest/c])
(formlet/c procedure?)]{
Constructs a @tech{formlet} with the rendering @racket[r] and the identity procedure as the processing step.
Constructs a @tech{formlet} with the rendering @racket[r] and the
identity procedure as the processing step.
}
@defproc[(xml [r xexpr/c])
@ -250,8 +250,10 @@ types. Refer to @secref["input-formlets"] for example low-level formlets using t
[attrs (listof (list/c symbol? string?))]
[inner (formlet/c any/c)])
(formlet/c any/c)]{
Constructs a @tech{formlet} with the rendering @racket[(list (list* tag attrs inner-rendering))] where @racket[inner-rendering] is
the rendering of @racket[inner] and the processing stage identical to @racket[inner].
Constructs a @tech{formlet} with the rendering @racket[(list (list*
tag attrs inner-rendering))] where @racket[inner-rendering] is the
rendering of @racket[inner] and the processing stage identical to
@racket[inner].
}
@defproc[(formlet-display [f (formlet/c any/c)])
@ -276,14 +278,15 @@ These @tech{formlet}s are the main combinators for form input.
@defproc[(make-input [render (string? . -> . xexpr/c)])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} is rendered with @racket[render], which is passed the input name, and results in the
extracted @racket[binding].
This @tech{formlet} is rendered with @racket[render], which is passed
the input name, and results in the extracted @racket[binding].
}
@defproc[(make-input* [render (string? . -> . xexpr/c)])
(formlet/c (listof binding?))]{
This @tech{formlet} is rendered with @racket[render], which is passed the input name, and results in all the
@racket[binding]s that use the name.
This @tech{formlet} is rendered with @racket[render], which is passed
the input name, and results in all the @racket[binding]s that use the
name.
}
@defproc[(text-input [#:value value (or/c false/c bytes?) #f]
@ -292,7 +295,8 @@ These @tech{formlet}s are the main combinators for form input.
[#:read-only? read-only? boolean? #f]
[#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an INPUT element with the TEXT type and the attributes given in the arguments.
This @tech{formlet} renders using an INPUT element with the TEXT type
and the attributes given in the arguments.
}
@defproc[(password-input [#:value value (or/c false/c bytes?) #f]
@ -301,7 +305,8 @@ These @tech{formlet}s are the main combinators for form input.
[#:read-only? read-only? boolean? #f]
[#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an INPUT element with the PASSWORD type and the attributes given in the arguments.
This @tech{formlet} renders using an INPUT element with the PASSWORD
type and the attributes given in the arguments.
}
@defproc[(textarea-input [#:value value (or/c false/c bytes?) #f]
@ -309,14 +314,16 @@ These @tech{formlet}s are the main combinators for form input.
[#:cols cols (or/c false/c number?) #f]
[#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an TEXTAREA element with attributes given in the arguments.
This @tech{formlet} renders using an TEXTAREA element with attributes
given in the arguments.
}
@defproc[(checkbox [value bytes?]
[checked? boolean?]
[#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an INPUT element with the CHECKBOX type and the attributes given in the arguments.
This @tech{formlet} renders using an INPUT element with the CHECKBOX
type and the attributes given in the arguments.
}
@defproc[(radio [value bytes?]
@ -329,23 +336,27 @@ These @tech{formlet}s are the main combinators for form input.
@defproc[(submit [value bytes?]
[#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an INPUT element with the SUBMIT type and the attributes given in the arguments.
This @tech{formlet} renders using an INPUT element with the SUBMIT
type and the attributes given in the arguments.
}
@defproc[(reset [value bytes?]
[#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an INPUT element with the RESET type and the attributes given in the arguments.
This @tech{formlet} renders using an INPUT element with the RESET type
and the attributes given in the arguments.
}
@defproc[(file-upload [#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an INPUT element with the FILE type and the attributes given in the arguments.
This @tech{formlet} renders using an INPUT element with the FILE type
and the attributes given in the arguments.
}
@defproc[(hidden [value bytes?] [#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an INPUT element with HIDDEN type and the attributes given in the arguments.
This @tech{formlet} renders using an INPUT element with HIDDEN type
and the attributes given in the arguments.
}
@defproc[(img [alt bytes?]
@ -356,7 +367,8 @@ These @tech{formlet}s are the main combinators for form input.
[#:width width (or/c false/c exact-nonnegative-integer?) #f]
[#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using an IMG element with the attributes given in the arguments.
This @tech{formlet} renders using an IMG element with the attributes
given in the arguments.
}
@defproc[(button [type bytes?]
@ -365,7 +377,9 @@ These @tech{formlet}s are the main combinators for form input.
[#:value value (or/c false/c bytes?) #f]
[#:attributes attrs (listof (list/c symbol? string?)) empty])
(formlet/c (or/c false/c binding?))]{
This @tech{formlet} renders using a BUTTON element with the attributes given in the arguments. @racket[button-text] is the text that will appear on the button when rendered.
This @tech{formlet} renders using a BUTTON element with the attributes
given in the arguments. @racket[button-text] is the text that will
appear on the button when rendered.
}
@defproc[(multiselect-input [l sequence?]
@ -374,7 +388,11 @@ These @tech{formlet}s are the main combinators for form input.
[#:selected? selected? (any/c . -> . boolean?) (λ (x) #f)]
[#:display display (any/c . -> . xexpr/c) (λ (x) x)])
(formlet/c list?)]{
This @tech{formlet} renders using an SELECT element with the attributes given with an OPTION for each element of the sequence. If @racket[multiple?] is @racket[#t], then multiple options may be selected. An element is selected if @racket[selected?] returns @racket[#t]. Elements are displayed with @racket[display].
This @tech{formlet} renders using an SELECT element with the
attributes given with an OPTION for each element of the sequence. If
@racket[multiple?] is @racket[#t], then multiple options may be
selected. An element is selected if @racket[selected?] returns
@racket[#t]. Elements are displayed with @racket[display].
}
@defproc[(select-input [l sequence?]
@ -382,39 +400,50 @@ These @tech{formlet}s are the main combinators for form input.
[#:selected? selected? (any/c . -> . boolean?) (λ (x) #f)]
[#:display display (any/c . -> . xexpr/c) (λ (x) x)])
(formlet/c any/c)]{
This @tech{formlet} renders using an SELECT element with the attributes given with an OPTION for each element of the sequence. An element is selected if @racket[selected?] returns @racket[#t]. Elements are displayed with @racket[display].
This @tech{formlet} renders using an SELECT element with the
attributes given with an OPTION for each element of the sequence. An
element is selected if @racket[selected?] returns
@racket[#t]. Elements are displayed with @racket[display].
}
@defproc[(required [f (formlet/c (or/c false/c binding?))])
(formlet/c bytes?)]{
Constructs a @tech{formlet} that extracts the @racket[binding:form-value] from the binding produced by @racket[f], or errors.
Constructs a @tech{formlet} that extracts the
@racket[binding:form-value] from the binding produced by @racket[f],
or errors.
}
@defproc[(default
[def bytes?]
[f (formlet/c (or/c false/c binding?))])
(formlet/c bytes?)]{
Constructs a @tech{formlet} that extracts the @racket[binding:form-value] from the binding produced by @racket[f], or returns @racket[def].
Constructs a @tech{formlet} that extracts the
@racket[binding:form-value] from the binding produced by @racket[f],
or returns @racket[def].
}
@defproc[(to-string [f (formlet/c bytes?)])
(formlet/c string?)]{
Converts @racket[f]'s output to a string. Equivalent to @racket[(cross (pure bytes->string/utf-8) f)].
Converts @racket[f]'s output to a string. Equivalent to
@racket[(cross (pure bytes->string/utf-8) f)].
}
@defproc[(to-number [f (formlet/c string?)])
(formlet/c number?)]{
Converts @racket[f]'s output to a number. Equivalent to @racket[(cross (pure string->number) f)].
Converts @racket[f]'s output to a number. Equivalent to @racket[(cross
(pure string->number) f)].
}
@defproc[(to-symbol [f (formlet/c string?)])
(formlet/c symbol?)]{
Converts @racket[f]'s output to a symbol. Equivalent to @racket[(cross (pure string->symbol) f)].
Converts @racket[f]'s output to a symbol. Equivalent to
@racket[(cross (pure string->symbol) f)].
}
@defproc[(to-boolean [f (formlet/c bytes?)])
(formlet/c boolean?)]{
Converts @racket[f]'s output to a boolean, if it is equal to @racket[#"on"].
Converts @racket[f]'s output to a boolean, if it is equal to
@racket[#"on"].
}
@defthing[input-string (formlet/c string?)]{
@ -446,16 +475,18 @@ A few utilities are provided for using @tech{formlet}s in Web applications.
`(html (head (title "Form Entry"))
(body ,form-xexpr)))])
(values any/c ...)]{
Uses @racket[send/suspend] and @racket[response/xexpr] to send @racket[f]'s rendering (wrapped in a FORM tag whose action is
the continuation URL (wrapped again by @racket[wrapper])) to the client.
When the form is submitted, the request is passed to the
processing stage of @racket[f].
Uses @racket[send/suspend] and @racket[response/xexpr] to send
@racket[f]'s rendering (wrapped in a FORM tag whose action is the
continuation URL (wrapped again by @racket[wrapper])) to the client.
When the form is submitted, the request is passed to the processing
stage of @racket[f].
}
@defproc[(embed-formlet [embed/url ((request? . -> . any) . -> . string?)]
[f (formlet/c any/c ...)])
xexpr/c]{
Like @racket[send/formlet], but for use with @racket[send/suspend/dispatch].
Like @racket[send/formlet], but for use with
@racket[send/suspend/dispatch].
}
}

View File

@ -278,8 +278,9 @@ transmission that the server @bold{will not catch}.}
[domain (or/c false/c valid-domain?)]
[path (or/c false/c string?)])]{
While server cookies are represented with @racket[cookie?]s, cookies that come from the client are represented
with a @racket[client-cookie] structure.
While server cookies are represented with @racket[cookie?]s, cookies
that come from the client are represented with a
@racket[client-cookie] structure.
}
@defproc[(request-cookies [req request?])
@ -423,15 +424,19 @@ An implementation of HTTP Digest Authentication.
@defproc[(password->digest-HA1 [lookup-password username*realm->password/c])
username*realm->digest-HA1/c]{
Uses @racket[lookup-password] to find the password, then computes the secret hash of it.
Uses @racket[lookup-password] to find the password, then computes the
secret hash of it.
}
@defproc[(make-check-digest-credentials [lookup-HA1 username*realm->digest-HA1/c])
(string? (listof (cons/c symbol? string?)) . -> . boolean?)]{
Constructs a function that checks whether particular Digest credentials (the second argument of the returned function)
are correct given the HTTP method provided as the first argument and the secret hash computed by @racket[lookup-HA1].
Constructs a function that checks whether particular Digest credentials
(the second argument of the returned function) are correct given the
HTTP method provided as the first argument and the secret hash computed
by @racket[lookup-HA1].
This is will result in an exception if the Digest credentials are missing portions.
This is will result in an exception if the Digest credentials are
missing portions.
}
Example:

View File

@ -21,10 +21,11 @@ of @racketmodname[web-server/dispatchers/dispatch-servlets].
@defproc[(make-make-servlet-namespace (#:to-be-copied-module-specs to-be-copied-module-specs (listof module-path?)))
make-servlet-namespace/c]{
This function creates a function that when called will construct a new @racket[namespace] that
has all the modules from @racket[to-be-copied-module-specs] and @racket[additional-specs], as well
as @racket[racket] and @racket[mred], provided they are already attached
to the @racket[(current-namespace)] of the call-site.
This function creates a function that when called will construct a new
@racket[namespace] that has all the modules from
@racket[to-be-copied-module-specs] and @racket[additional-specs], as
well as @racket[racket] and @racket[mred], provided they are already
attached to the @racket[(current-namespace)] of the call-site.
Example:
@racketblock[
@ -37,14 +38,17 @@ Example:
@section{Why this is useful}
A different namespace is needed for each servlet, so that if servlet A and servlet B both use
a stateful module C, they will be isolated from one another. We see the @web-server as
an operating system for servlets, so we inherit the isolation requirement on operating systems.
A different namespace is needed for each servlet, so that if servlet A
and servlet B both use a stateful module C, they will be isolated from
one another. We see the @web-server as an operating system for servlets,
so we inherit the isolation requirement on operating systems.
However, there are some modules which must be shared. If they were not, then structures cannot
be passed from the @web-server to the servlets, because Racket's structures are generative.
However, there are some modules which must be shared. If they were not,
then structures cannot be passed from the @web-server to the servlets,
because Racket's structures are generative.
Since, on occasion, a user will actually wanted servlets A and B to interact through module C.
A custom @racket[make-servlet-namespace] can be created, through this procedure, that attaches
module C to all servlet namespaces. Through other means (see @secref["dispatchers"]) different sets
of servlets can share different sets of modules.
Since, on occasion, a user will actually wanted servlets A and B to
interact through module C. A custom @racket[make-servlet-namespace] can
be created, through this procedure, that attaches module C to all
servlet namespaces. Through other means (see @secref["dispatchers"])
different sets of servlets can share different sets of modules.

View File

@ -9,12 +9,17 @@
@defmodule[web-server/lang/native]{
It is sometimes inconvenient to use @racket[serial->native] and @racket[native->serial] throughout your program.
This module provides a macro for creating wrappers.
It is sometimes inconvenient to use @racket[serial->native] and
@racket[native->serial] throughout your program. This module provides a
macro for creating wrappers.
@defform[#:literals (ho) (define-native (native arg-spec ...) original) #:contracts ([arg-spec ho] [arg-spec _])]{
Builds an interface around @racket[original] named @racket[native] such that calls to @racket[native] are wrapped in @racket[serial->native]
and all arguments marked with @racket[ho] in @racket[arg-spec] are assumed to procedures and are wrapped in @racket[native->serial].
@defform[#:literals (ho)
(define-native (native arg-spec ...) original)
#:contracts ([arg-spec ho] [arg-spec _])]{
Builds an interface around @racket[original] named @racket[native] such
that calls to @racket[native] are wrapped in @racket[serial->native]
and all arguments marked with @racket[ho] in @racket[arg-spec] are
assumed to procedures and are wrapped in @racket[native->serial].
For example,
@racketblock[

View File

@ -39,33 +39,59 @@ A simple example:
"You clicked!"))])
"Click me")))))]
Similarly, many Web applications make use almost exclusively of functions that are arguments to @racket[embed/url] and immediately invoke @racket[send/suspend/dispatch].
Similarly, many Web applications make use almost exclusively of
functions that are arguments to @racket[embed/url] and immediately
invoke @racket[send/suspend/dispatch].
@deftogether[[@defform[(lambda/page formals e ...)]
@defform[(define/page (id . formals) e ...)]]]{
The @racket[lambda/page] and @racket[define/page] automate this by expanding to functions that accept a request as the first argument (followed by any arguments specified in @racket[formals]) and immediately wrap their body in @racket[page]. This functions also cooperate with @racket[get-binding] by binding the request to the @racket[current-request] parameter.
The @racket[lambda/page] and @racket[define/page] automate this by
expanding to functions that accept a request as the first argument
(followed by any arguments specified in @racket[formals]) and
immediately wrap their body in @racket[page]. This functions also
cooperate with @racket[get-binding] by binding the request to the
@racket[current-request] parameter.
}
The binding interface of @racketmodname[web-server/http] is powerful, but subtle to use conveniently due to its protection against hostile clients.
The binding interface of @racketmodname[web-server/http] is powerful,
but subtle to use conveniently due to its protection against hostile
clients.
@deftogether[[
@defparam[current-request req request?]
@defthing[binding-id/c contract?]
@defthing[binding-format/c contract?]
@defproc[(get-binding [id binding-id/c] [req request? (current-request)] [#:format format binding-format/c 'string])
@defproc[(get-binding [id binding-id/c]
[req request? (current-request)]
[#:format format binding-format/c 'string])
(or/c false/c string? bytes? binding?)]
@defproc[(get-bindings [id binding-id/c] [req request? (current-request)] [#:format format binding-format/c 'string])
@defproc[(get-bindings [id binding-id/c]
[req request? (current-request)]
[#:format format binding-format/c 'string])
(listof (or/c string? bytes? binding?))]
]]{
The @racket[get-binding](s) interface attempts to resolve this by providing a powerful interface with convenient defaults.
The @racket[get-binding](s) interface attempts to resolve this by
providing a powerful interface with convenient defaults.
@racket[get-binding] extracts the first binding of a form input from a request, while @racket[get-bindings] extracts them all.
@racket[get-binding] extracts the first binding of a form input from a
request, while @racket[get-bindings] extracts them all.
They accept a form identifier (@racket[id]) as either a byte string, a string, or a symbol. In each case, the user input is compared in a case-sensitive way with the form input.
They accept a form identifier (@racket[id]) as either a byte string, a
string, or a symbol. In each case, the user input is compared in a
case-sensitive way with the form input.
They accept an optional request argument (@racket[req]) that defaults to the value of the @racket[current-request] parameter used by @racket[lambda/page] and @racket[define/page].
They accept an optional request argument (@racket[req]) that defaults
to the value of the @racket[current-request] parameter used by
@racket[lambda/page] and @racket[define/page].
Finally, they accept an optional keyword argument (@racket[format]) that specifies the desired return format. The default, @racket['string], produces a UTF-8 string (or @racket[#f] if the byte string cannot be converted to UTF-8.) The @racket['bytes] format always produces the raw byte string. The @racket['file] format produces the file upload content (or @racket[#f] if the form input was not an uploaded file.) The @racket['binding] format produces the binding object.
Finally, they accept an optional keyword argument (@racket[format])
that specifies the desired return format. The default,
@racket['string], produces a UTF-8 string (or @racket[#f] if the byte
string cannot be converted to UTF-8.) The @racket['bytes] format
always produces the raw byte string. The @racket['file] format
produces the file upload content (or @racket[#f] if the form input was
not an uploaded file.) The @racket['binding] format produces the
binding object.
}

View File

@ -8,70 +8,88 @@
@defmodule[web-server/configuration/responders]{
This module provides some functions that help constructing HTTP responders.
These functions are used by the default dispatcher constructor (see @secref["web-server-unit"]) to
turn the paths given in the @racket[configuration-table] into responders for the associated circumstance.
This module provides some functions that help constructing HTTP
responders. These functions are used by the default dispatcher
constructor (see @secref["web-server-unit"]) to turn the paths given in
the @racket[configuration-table] into responders for the associated
circumstance.
@defproc[(file-response (http-code natural-number/c) (short-version string?) (text-file string?) (header header?) ...)
@defproc[(file-response [http-code natural-number/c]
[short-version string?]
[text-file string?]
[header header?] ...)
response?]{
Generates a @racket[response?] with the given @racket[http-code] and @racket[short-version]
as the corresponding fields; with the content of the @racket[text-file] as the body; and, with
the @racket[header]s as, you guessed it, headers.
Generates a @racket[response?] with the given @racket[http-code] and
@racket[short-version] as the corresponding fields; with the content of
the @racket[text-file] as the body; and, with the @racket[header]s as,
you guessed it, headers.
This does not cause redirects to a well-known URL, such as @filepath{conf/not-found.html}, but rather use the contents
of @filepath{not-found.html} (for example) as its contents. Therefore, any relative URLs in @racket[text-file] are relative
to whatever URL @racket[file-response] is used to respond @emph{to}. Thus, you should probably use absolute URLs in these files.
This does not cause redirects to a well-known URL, such as
@filepath{conf/not-found.html}, but rather use the contents of
@filepath{not-found.html} (for example) as its contents. Therefore, any
relative URLs in @racket[text-file] are relative to whatever URL
@racket[file-response] is used to respond @emph{to}. Thus, you should
probably use absolute URLs in these files.
}
@defproc[(servlet-loading-responder (url url?) (exn exn?))
@defproc[(servlet-loading-responder [url url?] [exn exn?])
response?]{
Gives @racket[exn] to the @racket[current-error-handler] and response with a stack trace and a "Servlet didn't load" message.
Gives @racket[exn] to the @racket[current-error-handler] and response
with a stack trace and a "Servlet didn't load" message.
}
@defproc[(gen-servlet-not-found (file path-string?))
@defproc[(gen-servlet-not-found [file path-string?])
((url url?) . -> . response?)]{
Returns a function that generates a standard "Servlet not found." error with content from @racket[file].
Returns a function that generates a standard "Servlet not found." error
with content from @racket[file].
}
@defproc[(servlet-error-responder (url url?) (exn exn?))
@defproc[(servlet-error-responder [url url?] [exn exn?])
response?]{
Gives @racket[exn] to the @racket[current-error-handler] and response with a stack trace and a "Servlet error" message.
Gives @racket[exn] to the @racket[current-error-handler] and response
with a stack trace and a "Servlet error" message.
}
@defproc[(gen-servlet-responder (file path-string?))
@defproc[(gen-servlet-responder [file path-string?])
((url url?) (exn any/c) . -> . response?)]{
Prints the @racket[exn] to standard output and responds with a "Servlet error." message with content from @racket[file].
Prints the @racket[exn] to standard output and responds with a "Servlet
error." message with content from @racket[file].
}
@defproc[(gen-servlets-refreshed (file path-string?))
@defproc[(gen-servlets-refreshed [file path-string?])
(-> response?)]{
Returns a function that generates a standard "Servlet cache refreshed." message with content from @racket[file].
Returns a function that generates a standard "Servlet cache refreshed."
message with content from @racket[file].
}
@defproc[(gen-passwords-refreshed (file path-string?))
@defproc[(gen-passwords-refreshed [file path-string?])
(-> response?)]{
Returns a function that generates a standard "Passwords refreshed." message with content from @racket[file].
Returns a function that generates a standard "Passwords refreshed."
message with content from @racket[file].
}
@defproc[(gen-authentication-responder (file path-string?))
@defproc[(gen-authentication-responder [file path-string?])
((url url?) (header header?) . -> . response?)]{
Returns a function that generates an authentication failure error with content from @racket[file] and
@racket[header] as the HTTP header.
Returns a function that generates an authentication failure error with
content from @racket[file] and @racket[header] as the HTTP header.
}
@defproc[(gen-protocol-responder (file path-string?))
@defproc[(gen-protocol-responder [file path-string?])
((url url?) . -> . response?)]{
Returns a function that generates a "Malformed request" error with content from @racket[file].
Returns a function that generates a "Malformed request" error with
content from @racket[file].
}
@defproc[(gen-file-not-found-responder (file path-string?))
@defproc[(gen-file-not-found-responder [file path-string?])
((req request?) . -> . response?)]{
Returns a function that generates a standard "File not found" error with content from @racket[file].
Returns a function that generates a standard "File not found" error
with content from @racket[file].
}
@defproc[(gen-collect-garbage-responder (file path-string?))
@defproc[(gen-collect-garbage-responder [file path-string?])
(-> response?)]{
Returns a function that generates a standard "Garbage collection run" message with content from @racket[file].
Returns a function that generates a standard "Garbage collection run"
message with content from @racket[file].
}
}

View File

@ -23,7 +23,10 @@ and increasing the size of the serialization. This module provides support for t
@defproc[(soft-state-ref [ss soft-state?])
any/c]{
Extracts the value associated with @racket[ss]. If the value is not available (perhaps because of garbage collection, deserialization in an uninitialized process, etc), then the thunk associated with @racket[ss] is invoked and the value is cached.
Extracts the value associated with @racket[ss]. If the value is not
available (perhaps because of garbage collection, deserialization in an
uninitialized process, etc), then the thunk associated with @racket[ss]
is invoked and the value is cached.
}
@defform[(soft-state expr ...)]{

View File

@ -6,10 +6,11 @@
@title[#:tag "considerations"]{Usage Considerations}
A stateless servlet has the following process performed on it automatically:
A stateless servlet has the following process performed on it
automatically:
@itemize[
@item{All uses of @racket[letrec] are removed and replaced with equivalent uses of
@racket[let] and imperative features.}
@item{All uses of @racket[letrec] are removed and replaced with
equivalent uses of @racket[let] and imperative features.}
@item{The program is converted into @link["http://en.wikipedia.org/wiki/Administrative_normal_form"]{ANF} (Administrative Normal Form),
making all continuations explicit.}
@item{All continuations and continuations marks are recorded in the
@ -22,41 +23,47 @@ A stateless servlet has the following process performed on it automatically:
@racket[lambda].}
]
This process allows the continuations captured by your servlet to be serialized.
This means they may be stored on the client's browser or the server's disk.
This process allows the continuations captured by your servlet to be
serialized. This means they may be stored on the client's browser or
the server's disk.
This means your servlet has no cost to the server other than execution. This is
very attractive if you've used Racket servlets and had memory problems.
This means your servlet has no cost to the server other than
execution. This is very attractive if you've used Racket servlets and
had memory problems.
This means your server can restart in the middle of a long running Web interaction
without the URLs that have been shared with the client expiring. This is
very attractive if you've used Racket servlets and had session timeout problems.
This means your server can restart in the middle of a long running Web
interaction without the URLs that have been shared with the client
expiring. This is very attractive if you've used Racket servlets and
had session timeout problems.
This process is defined on all of Racket and occurs after macro-expansion,
so you are free to use all interesting features of Racket. However, there
are some considerations you must make.
This process is defined on all of Racket and occurs after
macro-expansion, so you are free to use all interesting features of
Racket. However, there are some considerations you must make.
First, this process drastically changes the structure of your program. It
will create an immense number of lambdas and structures your program
did not normally contain. The performance implication of this has not been
studied with Racket.
First, this process drastically changes the structure of your program.
It will create an immense number of lambdas and structures your program
did not normally contain. The performance implication of this has not
been studied with Racket.
Second, the defunctionalization process is sensitive to the syntactic structure
of your program. Therefore, if you change your program in a trivial way, for example,
changing a constant, then all serialized continuations will be obsolete and will
error when deserialization is attempted. This is a feature, not a bug! It is a small
price to pay for protection from the sorts of errors that would occur if your program
Second, the defunctionalization process is sensitive to the syntactic
structure of your program. Therefore, if you change your program in a
trivial way, for example, changing a constant, then all serialized
continuations will be obsolete and will error when deserialization is
attempted. This is a feature, not a bug! It is a small price to pay for
protection from the sorts of errors that would occur if your program
were changed in a meaningful way.
Third, the values in the lexical scope of your continuations must be serializable
for the continuations itself to be serializable. This means that you must use
@racket[define-serializable-struct] rather than @racket[define-struct], and take
care to use modules that do the same. Similarly, you may not use @racket[parameterize],
because parameterizations are not serializable.
Third, the values in the lexical scope of your continuations must be
serializable for the continuations itself to be serializable. This means
that you must use @racket[define-serializable-struct] rather than
@racket[define-struct], and take care to use modules that do the same.
Similarly, you may not use @racket[parameterize], because
parameterizations are not serializable.
Fourth, and related, this process only runs on your code, not on the code you
@racket[require]. Thus, your continuations---to be serializable---must not
be in the context of another module. For example, the following will fail with an @as-index{"unsafe context"}
Fourth, and related, this process only runs on your code, not on the
code you @racket[require]. Thus, your continuations---to be
serializable---must not be in the context of another module. For
example, the following will fail with an @as-index{"unsafe context"}
exception:
@racketblock[

View File

@ -52,8 +52,9 @@ You can supply your own (built with these functions) when you write a stateless
@defproc[(stuffer-compose [g (stuffer/c any/c any/c)]
[f (stuffer/c any/c any/c)])
(stuffer/c any/c any/c)]{
Composes @racket[f] and @racket[g], i.e., applies @racket[f] then @racket[g] for @racket[in]
and @racket[g] then @racket[f] for @racket[out].
Composes @racket[f] and @racket[g], i.e., applies @racket[f] then
@racket[g] for @racket[in] and @racket[g] then @racket[f] for
@racket[out].
}
@defproc[(stuffer-sequence [f (stuffer/c any/c any/c)]
@ -65,9 +66,10 @@ You can supply your own (built with these functions) when you write a stateless
@defproc[(stuffer-if [c (bytes? . -> . boolean?)]
[f (stuffer/c bytes? bytes?)])
(stuffer/c bytes? bytes?)]{
Creates a @tech{stuffer} that stuffs with @racket[f] if @racket[c] is true on the input
to @racket[in]. Similarly, applies @racket[f] during @racket[out] if it was applied during
@racket[in] (which is recorded by prepending a byte.)
Creates a @tech{stuffer} that stuffs with @racket[f] if @racket[c] is
true on the input to @racket[in]. Similarly, applies @racket[f] during
@racket[out] if it was applied during @racket[in] (which is recorded by
prepending a byte.)
}
@defproc[(stuffer-chain [x (or/c stuffer? (bytes? . -> . boolean?))]
@ -85,7 +87,8 @@ You can supply your own (built with these functions) when you write a stateless
@defmodule[web-server/stuffers/serialize]{
@defthing[serialize-stuffer (stuffer/c serializable? bytes?)]{
A @tech{stuffer} that uses @racket[serialize] and @racket[write/bytes] and @racket[deserialize] and @racket[read/bytes].
A @tech{stuffer} that uses @racket[serialize] and @racket[write/bytes]
and @racket[deserialize] and @racket[read/bytes].
}
}
@ -111,14 +114,16 @@ You can supply your own (built with these functions) when you write a stateless
@defthing[gzip-stuffer (stuffer/c bytes? bytes?)]{
A @tech{stuffer} that uses @racket[gzip/bytes] and @racket[gunzip/bytes].
@warning{You should compose this with @racket[base64-stuffer] to get URL-safe bytes.}
@warning{You should compose this with @racket[base64-stuffer] to get
URL-safe bytes.}
}
}
@section{Key/Value Storage}
The @racketmodname[web-server/stuffers/hash] @tech{stuffers} rely on a key/value store.
The @racketmodname[web-server/stuffers/hash] @tech{stuffers} rely on a
key/value store.
@defmodule[web-server/stuffers/store]{
@ -155,8 +160,10 @@ The @racketmodname[web-server/stuffers/hash] @tech{stuffers} rely on a key/value
@defproc[(hash-stuffer [H hash-fun/c]
[store store?])
(stuffer/c bytes? bytes?)]{
A content-addressed storage @tech{stuffer} that stores input bytes, @racket[input], in @racket[store] with the key @racket[(H input)]
and returns the key. Similarly, on @racket[out] the original bytes are looked up.
A content-addressed storage @tech{stuffer} that stores input bytes,
@racket[input], in @racket[store] with the key @racket[(H input)] and
returns the key. Similarly, on @racket[out] the original bytes are
looked up.
}
@defproc[(md5-stuffer [root path-string?])
@ -172,24 +179,32 @@ The @racketmodname[web-server/stuffers/hash] @tech{stuffers} rely on a key/value
@defproc[(HMAC-SHA1 [kb bytes?] [db bytes?])
bytes?]{
Performs a HMAC-SHA1 calculation on @racket[db] using @racket[kb] as the key. The result is guaranteed to be 20 bytes.
(You could curry this to use it with @racket[hash-stuffer], but there is little value in doing so over @racket[md5].)
Performs a HMAC-SHA1 calculation on @racket[db] using @racket[kb] as
the key. The result is guaranteed to be 20 bytes. (You could curry
this to use it with @racket[hash-stuffer], but there is little value
in doing so over @racket[md5].)
}
@defproc[(HMAC-SHA1-stuffer [kb bytes?])
(stuffer/c bytes? bytes?)]{
A @tech{stuffer} that signs input using @racket[HMAC-SHA1] with @racket[kb] as the key. The result of the @tech{stuffer} is
the hash prepended to the input data. When the @tech{stuffer} is run in reverse, it checks if the first 20 bytes are the correct
has for the rest of the data.
A @tech{stuffer} that signs input using @racket[HMAC-SHA1] with
@racket[kb] as the key. The result of the @tech{stuffer} is the hash
prepended to the input data. When the @tech{stuffer} is run in
reverse, it checks if the first 20 bytes are the correct has for the
rest of the data.
@warning{You should compose this with @racket[base64-stuffer] to get URL-safe bytes.}
@warning{You should compose this with @racket[base64-stuffer] to get
URL-safe bytes.}
@warning{Without explicit provision, it is possible for users to modify the continuations they are sent through the other @tech{stuffers}.
This @tech{stuffer} allows the servlet to certify that stuffed data was truly generated by the servlet. Therefore, you @bold{should} use this
if you are not using the @racket[hash-stuffer]s.}
@warning{Without explicit provision, it is possible for users to
modify the continuations they are sent through the other
@tech{stuffers}. This @tech{stuffer} allows the servlet to certify
that stuffed data was truly generated by the servlet. Therefore, you
@bold{should} use this if you are not using the
@racket[hash-stuffer]s.}
@warning{This @tech{stuffer} does @bold{not} encrypt the data in anyway, so users can still observe the stuffed values.}
@warning{This @tech{stuffer} does @bold{not} encrypt the data in
anyway, so users can still observe the stuffed values.}
}
}
@ -200,14 +215,17 @@ The @racketmodname[web-server/stuffers/hash] @tech{stuffers} rely on a key/value
@defproc[(is-url-too-big? [v bytes?])
boolean?]{
Determines if stuffing @racket[v] into the current servlet's URL would result in a URL that is too big for Internet Explorer.
(@link["http://www.boutell.com/newfaq/misc/urllength.html"]{IE only supports URLs up to 2048 characters.})
Determines if stuffing @racket[v] into the current servlet's URL would
result in a URL that is too big for Internet Explorer.
(@link["http://www.boutell.com/newfaq/misc/urllength.html"]{IE only
supports URLs up to 2048 characters.})
}
@defproc[(make-default-stuffer [root path-string?])
(stuffer/c serializable? bytes?)]{
Constructs a @tech{stuffer} that serializes, then if the URL is too big, compresses (and base64-encodes), if the URL is still too big
then it stores it in an MD5-indexed database rooted at @racket[root].
Constructs a @tech{stuffer} that serializes, then if the URL is too
big, compresses (and base64-encodes), if the URL is still too big then
it stores it in an MD5-indexed database rooted at @racket[root].
Equivalent to:
@racketblock[

View File

@ -36,7 +36,10 @@ This function accepts a servlet function and provides a function that accepts a
]
}
This facility is designed to be used in concert with a technique of extracting continuation URLs and relevant values; @racketmodname[xml/path] is one way to do this. Here is an extended example that tests an Add-Two-Numbers.com:
This facility is designed to be used in concert with a technique of
extracting continuation URLs and relevant values;
@racketmodname[xml/path] is one way to do this. Here is an extended
example that tests an Add-Two-Numbers.com:
@(require (for-label xml/path
rackunit
racket/list

View File

@ -105,7 +105,12 @@ represented as an X-expression in Racket, by using
For example:
The HTML @tt{hello} is represented as @racket["hello"]. Strings are automatically escaped when output. This guarantees valid HTML. Therefore, the value @racket["<b>Unfinished tag"] is rendered as @tt{&lt;b&gt;Unfinished tag} not @tt{<b>Unfinished tag}. Similarly, @racket["<i>Finished tag</i>"] is rendered as @tt{&lt;i&gt;Finished tag&lt;/i&gt;} not @tt{<i>Finished tag</i>}.
The HTML @tt{hello} is represented as @racket["hello"]. Strings are
automatically escaped when output. This guarantees valid HTML.
Therefore, the value @racket["<b>Unfinished tag"] is rendered as
@tt{&lt;b&gt;Unfinished tag} not @tt{<b>Unfinished tag}. Similarly,
@racket["<i>Finished tag</i>"] is rendered as
@tt{&lt;i&gt;Finished tag&lt;/i&gt;} not @tt{<i>Finished tag</i>}.
@tt{<p>This is an example</p>} is

View File

@ -212,6 +212,7 @@ functions of interest for the servlet developer.
returns the instance id, continuation id, and nonce.
}
@defthing[servlet-prompt continuation-prompt-tag?]{The tag used for Web interaction continuation capture.}
@defthing[servlet-prompt continuation-prompt-tag?]{
The tag used for Web interaction continuation capture.}
}

View File

@ -47,7 +47,8 @@ Represents a location in an input stream.}
@defstruct[source ([start location/c]
[stop location/c])]{
Represents a source location. Other structure types extend @racket[source].
Represents a source location. Other structure types extend
@racket[source].
When XML is generated from an input stream by @racket[read-xml],
locations are represented by @racket[location] instances. When XML
@ -174,7 +175,8 @@ and a @racket[_misc] is an instance of the @racket[comment] or
@racket[p-i] structure types.}
@defthing[xexpr/c contract?]{
A contract that is like @racket[xexpr?] except produces a better error message when the value is not an @tech{X-expression}.
A contract that is like @racket[xexpr?] except produces a better error
message when the value is not an @tech{X-expression}.
}
@; ----------------------------------------------------------------------