doc work (fix long filename)

svn: r6717
This commit is contained in:
Matthew Flatt 2007-06-22 12:19:03 +00:00
parent e0edc04bef
commit ff1189600a
5 changed files with 392 additions and 20 deletions

View File

@ -272,12 +272,16 @@
(current-subdirectory))
(super get-dest-directory)))
(define/private (derive-filename d)
(format "~a.html" (regexp-replace*
"[^-a-zA-Z0-9_=]"
(or (format "~a" (part-tag d))
(content->string (part-title-content d)))
"_")))
(define/private (derive-filename d ht)
(let ([fn (format "~a.html" (regexp-replace*
"[^-a-zA-Z0-9_=]"
(or (format "~a" (part-tag d))
(content->string (part-title-content d)
this d ht))
"_"))])
(when ((string-length fn) . >= . 100)
(error "file name too long (need a tag):" fn))
fn))
(define/override (collect ds fns)
(super collect ds (map (lambda (fn)
@ -297,7 +301,7 @@
1
(add1 prev-sub))])
(if (= 1 prev-sub)
(let ([filename (derive-filename d)])
(let ([filename (derive-filename d ht)])
(parameterize ([current-output-file (build-path (path-only (current-output-file))
filename)])
(super collect-part d parent ht number)))
@ -417,7 +421,7 @@
(make-element
(if parent
(make-target-url (if prev
(derive-filename prev)
(derive-filename prev ht)
"index.html"))
"nonavigation")
prev-content)
@ -426,14 +430,14 @@
(if parent
(make-target-url
(if (toc-part? parent)
(derive-filename parent)
(derive-filename parent ht)
"index.html"))
"nonavigation")
up-content)
sep-element
(make-element
(if next
(make-target-url (derive-filename next))
(make-target-url (derive-filename next ht))
"nonavigation")
next-content))))))))
d
@ -447,7 +451,7 @@
(next-separate-page)))
;; Render as just a link, and put the actual
;; content in a new file:
(let* ([filename (derive-filename d)]
(let* ([filename (derive-filename d ht)]
[full-path (build-path (path-only (current-output-file))
filename)])
(parameterize ([on-separate-page #t])

View File

@ -39,13 +39,13 @@ are built from @scheme[_struct-id] and the @scheme[_field-id]s:
@itemize{
@item{@schemeidfont{make-}@scheme[_struct-id] : a
@defterm{constructor} function that takes as many arguments as
@deftech{constructor} function that takes as many arguments as
the number of @scheme[_field-id]s, and returns an instance of
the structure type.
@examples[(make-posn 1 2)]}
@item{@scheme[_struct-id]@schemeidfont{?} : a @defterm{predicate}
@item{@scheme[_struct-id]@schemeidfont{?} : a @deftech{predicate}
function that takes a single argument and returns @scheme[#t]
if it is an instance of the structure type, @scheme[#f]
otherwise.
@ -53,14 +53,14 @@ are built from @scheme[_struct-id] and the @scheme[_field-id]s:
@examples[(posn? 3) (posn? (make-posn 1 2))]}
@item{@scheme[_struct-id]@schemeidfont{-}@scheme[_field-id] : for
each @scheme[_field-id], an @defterm{accessor} that extracts
each @scheme[_field-id], an @deftech{accessor} that extracts
the value of the corresponding field from an instance of the
structure type.
@examples[(posn-x (make-posn 1 2)) (posn-y (make-posn 1 2))]}
@item{@schemeidfont{set-}@scheme[_struct-id]@schemeidfont{-}@scheme[_field-id]@schemeidfont{!} : for
each @scheme[_field-id], a @defterm{mutator} that sets
each @scheme[_field-id], a @deftech{mutator} that sets
the value of the corresponding field in an instance of the
structure type.
@ -68,6 +68,12 @@ are built from @scheme[_struct-id] and the @scheme[_field-id]s:
(posn-x p)
(set-posn-x! p 10)
(posn-x p)]}
@item{@schemeidfont{struct:}@scheme[_struct-id] : a
@deftech{structure type descriptor}, which is a value that
represents the structure type (as opposed to a single instance)
for certain reflective operations.}
}
A @scheme[define-struct] form places no constraints on the kinds of
@ -76,7 +82,7 @@ type. For example, @scheme[(make-posn "apple" #f)] produces an
instance of @scheme[posn], even though @scheme["apple"] and
@scheme[#f] are not valid coordinates for the obvious uses of
@scheme[posn] instances. Enforcing constraints on field values, such
as requiring them to be numbers, is the job of a contract, as
as requiring them to be numbers, is normally the job of a contract, as
discussed later in @secref["guide:contracts"].
@; ------------------------------------------------------------
@ -114,7 +120,7 @@ p
]
@; ------------------------------------------------------------
@section{Opaque versus Transparent Stucture Types}
@section[#:tag "guide:trans-struct"]{Opaque versus Transparent Stucture Types}
With a structure type definition like
@ -141,11 +147,176 @@ field-name sequence:
An instance of a transparent structure type prints like a vector, and
it shows the content of the structure's fields. A transparent
structure type also allows reflective operations, like
@scheme[struct?] and @scheme[struct-info], to be used on its
instances (see @secref["reflection"]).
@scheme[struct?] and @scheme[struct-info], to be used on its instances
(see @secref["reflection"]). Different values for @scheme[#:inspector]
support more controlled access to reflective operations.
Structure types are opaque by default, because opaque structure
instances provide more encapsulation guarantees. That is, a library
can use an opaque structure to encapsulate data, and clients of the
library cannot manipulate the data in the structure except as allowed
by the library.
@; ------------------------------------------------------------
@section{More Structure Type Options}
The full syntax of @scheme[define-struct] supports many options, both
at the structure-type level and at the level of individual fields:
@specform/subs[(define-struct id-maybe-super (field ...)
struct-option ...)
([id-maybe-super struct-id
(struct-id super-id)]
[field field-id
[field-id field-option ...]])]
A @scheme[_struct-option] always starts with a keyword:
@specspecsubform[#:immutable]{
Causes all fields of the structure type to be immutable, and
supresses the definition of @tech{mutator} procedures.
@defexamples[(define-struct fixed-posn (x y) #:immutable)
(set-fixed-posn-x! (make-fixed-posn 1 2) 0)]
Th @scheme[#:immutable] option can also be used as a
@scheme[_field-option], in which case it makes an individual field
immutable.
@defexamples[
(define-struct person ([name #:immutable] age))
(define friend (make-person "Barney" 5))
(set-person-age! friend 6)
(set-person-name! friend "Mary")]}
@specspecsubform[(code:line #:inspector inspector-expr)]{
Controls reflective access to structure instances, as discussed
in the previous section (@secref["guide:trans-struct"]).
}
@specspecsubform[(code:line #:auto-value auto-expr)]{
Specifies a value to be used for all automatic fields in the
structure type, where an automatic field is indicated by the
@scheme[#:auto] @scheme[_field-option]. The structure type's
constructor omits arguments for automatic fields.
@defexamples[
(define-struct posn (x y [z #:auto])
#:inspector #f
#:auto-value 0)
(make-posn 1 2)
]}
@specspecsubform[(code:line #:guard guard-expr)]{
Specifies a guard procedure to be called whenever an instance of
the structure type is created. The guard takes as many arguments
as non-automatic fields in the structure type, and it should return
the same number of values. The guard can raise an exception if one
of the given arguments is unacceptable, or it can convert an
argument.
@defexamples[
(define-struct thing (name)
#:inspector #f
#:guard (lambda (name type-name)
(cond
[(string? name) name]
[(number? name)
(number->string name)]
[else (error "bad name" name)])))
(make-thing "apple")
(make-thing 1/2)
(make-thing #f)]
Unlike the constructor for a procedure type, the guard is called even when
subtype instances are created. In that case, only the fields accepted by
the constructor are provided to the guard (but the subtype's guard gets
both the original fields and fields added by the subtype).
@defexamples[
(define-struct (person thing) (age)
#:inspector #f
#:guard (lambda (name age type-name)
(if (negative? age)
(error "bad age" age)
(values name age))))
(make-person "John" 10)
(make-person "Mary" -1)
(make-person #f 10)]}
@specspecsubform[(code:line #:property prop-expr val-exr)]{
Associates a property and value with the structure type. For
example, the @scheme[prop:procedure] property allows a structure
instance to be used as a function; the property value determines
how a call is implemented when using the structure as a function.
@defexamples[
(define-struct greeter (name)
#:property prop:procedure
(lambda (self other)
(string-append
"Hi " other
", I'm " (greeter-name self))))
(define joe-greet (make-greeter "Joe"))
(greeter-name joe-greet)
(joe-greet "Mary")
(joe-greet "John")]}
@specspecsubform[(code:line #:super super-expr)]{
An alternative to supplying a @scheme[super-id] next to
@scheme[struct-id]. Instead of the name of a structure type (which is
not an expression), @scheme[super-expr] should produce a
@tech{structure type descriptor} value. An advantage of
@scheme[#:super] is that structure type descriptors are values, so
they can be passed to procedures.
@defexamples[
(define (make-raven-constructor super-type)
(define-struct raven ()
#:super super-type
#:inspector #f
#:property prop:procedure (lambda (self)
'nevermore))
make-raven)
(let ([r ((make-raven-constructor struct:posn) 1 2)])
(list r (r)))
(let ([r ((make-raven-constructor struct:thing) "apple")])
(list r (r)))]}
@; ------------------------------------------------------------
@section{Structure Type Generativity}
Each time that a @scheme[define-struct] form is evaluated, it
generates a structure type that is distinct from all existing
structure types, even if some other structure type has the same name
and fields.
This generativity is useful for enforcing abstractions and
implementing programs such as interpreters, but beware of placing a
@scheme[define-struct] form in positions that are evaluated multiple
times.
@defexamples[
(define (add-bigger-fish lst)
(define-struct fish (size) #:inspector #f)
(cond
[(null? lst) (list (make-fish 1))]
[else (cons (make-fish (* 2 (fish-size (car lst))))
lst)]))
(add-bigger-fish null)
(add-bigger-fish (add-bigger-fish null))
]
@defs+int[
[(define-struct fish (size) #:inspector #f)
(define (add-bigger-fish lst)
(cond
[(null? lst) (list (make-fish 1))]
[else (cons (make-fish (* 2 (fish-size (car lst))))
lst)]))]
(add-bigger-fish (add-bigger-fish null))
]

View File

@ -17,6 +17,7 @@ language.
@include-section["syntax.scrbl"]
@include-section["derived.scrbl"]
@include-section["data.scrbl"]
@include-section["struct.scrbl"]
@;------------------------------------------------------------------------

View File

@ -0,0 +1,196 @@
#reader(lib "docreader.ss" "scribble")
@require["mz.ss"]
@title[#:tag "mz:structures"]{Structures}
A @pidefterm{structure type} is a record datatype composing a number
of @idefterm{fields}. A @pidefterm{structure}, an instance of a
structure type, is a first-class value that contains a value for each
field of the structure type. A structure instance is created with a
type-specific @tech{constructor} procedure, and its field values are
accessed and changed with type-specific @tech{accessor} and
@tech{mutator} procedures. In addition, each structure type has a
@tech{predicate} procedure that answers @scheme[#t] for instances of
the structure type and @scheme[#f] for any other value.
A structure type's fields are essentially unnamed, though names are
supported for error-reporting purposes. The constructor procedure
takes one value for each field of the structure type, except that some
of the fields of a structure type can be @deftech{automatic fields};
the @tech{automatic fields} are initialized to a constant that is
associated with the structure type, and the corresponding arguments
are omitted for the constructor procedure. All automatic fields in a
structure type follow the non-automatic fields.
A structure type can be created as a @pidefterm{structure subtype} of
an existing base structure type. An instance of a structure subtype
can always be used as an instance of the base structure type, but the
subtype gets its own predicate procedure, and it may have its own
fields in addition to the fields of the base type.
A structure subtype ``inherits'' the fields of its base type. If the
base type has @math{m} fields, and if @math{n} fields are specified
for the new structure subtype, then the resulting structure type has
@math{m+n} fields. The value for automatic fields can be different in
a subtype than in its base type.
If @math{m'} of the original @math{m} fields are non-automatic (where
@math{m'<m}), and @math{n'} of the new fields are automatic (where
@math{n'<n}), then @math{m'+n'} field values must be provided to the
subtype's constructor procedure. Values for the first @math{m} fields
of a subtype instance are accessed with selector procedures for the
original base type (or its supertypes), and the last @math{n} are
accessed with subtype-specific selectors. Subtype-specific
@tech{accessors} and @tech{mutators} for the first @math{m} fields do
not exist.
@section{Creating Structure Types}
@defproc[(make-struct-type [name symbol?]
[super-type (or/c struct-type? false/c)]
[init-field-k non-negative-exact-integer?]
[auto-field-k non-negative-exact-integer?]
[auto-v any/c #f]
[props (listof (cons/c struct-type-property?
any/c))
null]
[inspector (or/c inspector? false/c)
(current-inspector)]
[proc-spec (or/c procedure?
non-negative-exact-integer?
false/c)
#f]
[immutables (listof non-negative-exact-integer?)
null]
[guard (or/c procedure? false/c) #f])
struct-type?]{
Creates a new structure type. The @scheme[name] argument is used as
the type name. If @scheme[super-type] is not @scheme[#f], the new type
is a subtype of the corresponding structure type.
The new structure type has @scheme[(+ init-field-k auto-field-k)]
fields (in addition to any fields from @scheme[super-type]), but only
@scheme[init-field-k] constructor arguments (in addition to any
constructor arguments from @scheme[super-type]). The remaining
fields are initialized with @scheme[auto-v].
The @scheme{props} argument is a list of pairs, where the @scheme[car]
of each pair is a structure type property descriptor, and the
@scheme[cdr] is an arbitrary value. See @secref["mz:structprops"] for
more information about properties.
The @scheme[inspector] argument controls access to reflective
information about the structure type and its instances; see
@secref["mz:inspectors"] for more information.
If @scheme[proc-spec] is an integer or procedure, instances of the
structure type act as procedures. See @secref["mz:procstructs"] for
further information. Providing a non-@scheme[#f] value for
@scheme[proc-spec] is the same as pairing the value with
@scheme[prop:procedure] in @scheme[props], plus including
@scheme[proc-spec] in @scheme[immutables] when
@scheme[proc-spec] is an integer.
The @scheme[immutables] argument provides a list of field
positions. Each element in the list must be unique, otherwise
@exnraise[exn:fail:contract]. Each element must also fall in the range
@scheme[0] (inclusive) to @scheme[init-field-k] (exclusive), otherwise
@exnraise[exn:fail:contract].
The @scheme[guard-proc] argument is either a procedure of @math{n}
arguments or @scheme[#f], where @math{n} is the number of arguments
for the new structure type's constructor (i.e., @scheme[init-field-k]
plus constructor arguments implied by @scheme[super-type], if any). If
@scheme[guard-proc] is a procedure, then the procedure is called
whenever an instance of the type is constructed, or whenever an
instance of a subtype is created. The arguments to
@scheme[guard-proc] are the values provided for the structure's first
@math{n} fields, followed by the name of the instantiated structure
type (which is @scheme[name], unless a subtype is instantiated). The
@scheme[guard-proc] result must be @math{n} values, which become the
actual values for the structure's fields. The @scheme[guard-proc] can
raise an exception to prevent creation of a structure with the given
field values. If a structure subtype has its own guard, the subtype
guard is applied first, and the first @math{n} values produced by the
subtype's guard procedure become the first @math{n} arguments to
@scheme[guard-proc].
The result of @scheme[make-struct-type] is five values:
%
@itemize{
@item{a @tech{structure type descriptor},}
@item{a @tech{constructor} procedure,}
@item{a @tech{predicate} procedure,}
@item{an @tech{accessor} procedure, which consumes a structure and a field
index between @math{0} (inclusive) and
@math{@scheme[init-field-k]+@scheme[auto-field-k]} (exclusive),
and}
@item{a @tech{mutator} procedure, which consumes a structure, a field
index, and a field value.}
}
@examples[
(define-values (struct:a make-a a? a-ref a-set!)
(make-struct-type 'a #f 2 1 'uninitialized))
(define an-a (make-a 'x 'y))
(a-ref an-a 1)
(a-ref an-a 2)
(define a-first (make-struct-field-accessor a-ref 0))
(a-first an-a)
(define-values (struct:b make-b b? b-ref b-set!)
(make-struct-type 'b struct:a 1 2 'b-uninitialized))
(define a-b (make-b 'x 'y 'z))
(a-ref a-b 1)
(a-ref a-b 2)
(b-ref a-b 0)
(b-ref a-b 1)
(b-ref a-b 2)
(define-values (struct:c make-c c? c-ref c-set!)
(make-struct-type 'c struct:b 0 0 #f null (make-inspector) #f null
(code:comment #,(t "guard checks for a number, and makes it inexact"))
(lambda (a1 a2 b1 name)
(unless (number? a2)
(error (string->symbol (format "make-~a" name))
"second field must be a number"))
(values a1 (exact->inexact a2) b1))))
(make-c 'x 'y 'z)
(define a-c (make-c 'x 2 'z))
(a-ref a-c 1)
]}
@defproc[(make-struct-field-accessor [accessor-proc procedure?]
[field-pos-k exact-nonnegative-integer?]
[field-name symbol?])
procedure?]{
Returns a field accessor that is equivalent to @scheme[(lambda (s)
(accessor-proc s field-pos-k))]. The @scheme[accessor-proc] must be
an @tech{accessor} returned by @scheme[make-struct-type]. The name of the
resulting procedure for debugging purposes is derived from
@scheme[field-name] and the name of @scheme[accessor-proc]'s
structure type.
For examples, see @scheme[make-struct-type].}
@defproc[(make-struct-field-mutator [mutator-proc procedure?]
[field-pos-k exact-nonnegative-integer?]
[field-name symbol?])
procedure?]{
Returns a field mutator that is equivalent to @scheme[(lambda (s v)
(mutator-proc s field-pos-k v))]. The @scheme[mutator-proc] must be
a @tech{mutator} returned by @scheme[make-struct-type]. The name of the
resulting procedure for debugging purposes is derived from
@scheme[field-name] and the name of @scheme[mutator-proc]'s
structure type.
For examples, see @scheme[make-struct-type].}

View File

@ -354,7 +354,7 @@ Like @scheme[lambda], but without support for keyword or optional arguments.
}
@;------------------------------------------------------------------------
@section{Local Binding: @scheme[let], @scheme[let*], and @scheme[letrec]}
@section[#:tag "mz:let"]{Local Binding: @scheme[let], @scheme[let*], and @scheme[letrec]}
@defform*[[(let ([id val-expr] ...) body ...+)
(let proc-id ([id init-expr] ...) body ...+)]]{