mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-10 05:50:26 +02:00
doc: Move SRFI-9 records under "Compound Data Types".
Suggested by Mark Weaver. * doc/ref/srfi-modules.texi (SRFI-9): Keep the node, but move contents to... * doc/ref/api-compound.texi (SRFI-9 Records): ...here. (Record Overview): New section.
This commit is contained in:
parent
3d01c19a78
commit
ec7e4f77ec
2 changed files with 153 additions and 103 deletions
|
@ -25,8 +25,10 @@ values can be looked up within them.
|
|||
* Generalized Vectors:: Treating all vector-like things uniformly.
|
||||
* Arrays:: Matrices, etc.
|
||||
* VLists:: Vector-like lists.
|
||||
* Records::
|
||||
* Structures::
|
||||
* Record Overview:: Walking through the maze of record APIs.
|
||||
* SRFI-9 Records:: The standard, recommended record API.
|
||||
* Records:: Guile's historical record API.
|
||||
* Structures:: Low-level record representation.
|
||||
* Dictionary Types:: About dictionary types in general.
|
||||
* Association Lists:: List-based dictionaries.
|
||||
* VHashes:: VList-based dictionaries.
|
||||
|
@ -2249,6 +2251,152 @@ Return a new vlist whose contents correspond to @var{lst}.
|
|||
Return a new list whose contents match those of @var{vlist}.
|
||||
@end deffn
|
||||
|
||||
@node Record Overview
|
||||
@subsection Record Overview
|
||||
|
||||
@cindex record
|
||||
@cindex structure
|
||||
|
||||
@dfn{Records}, also called @dfn{structures}, are Scheme's primary
|
||||
mechanism to define new disjoint types. A @dfn{record type} defines a
|
||||
list of @dfn{fields} that instances of the type consist of. This is like
|
||||
C's @code{struct}.
|
||||
|
||||
Historically, Guile has offered several different ways to define record
|
||||
types and to create records, offering different features, and making
|
||||
different trade-offs. Over the years, each ``standard'' has also come
|
||||
with its own new record interface, leading to a maze of record APIs.
|
||||
|
||||
At the highest level is SRFI-9, a high-level record interface
|
||||
implemented by most Scheme implementations (@pxref{SRFI-9}). It defines
|
||||
a simple and efficient syntactic abstraction of record types and their
|
||||
associated type predicate, fields, and field accessors. SRFI-9 is
|
||||
suitable for most uses, and this is the recommended way to create record
|
||||
types in Guile. Similar high-level record APIs include SRFI-35
|
||||
(@pxref{SRFI-35}) and R6RS records (@pxref{rnrs records syntactic}).
|
||||
|
||||
Then comes Guile's historical ``records'' API (@pxref{Records}). Record
|
||||
types defined this way are first-class objects. Introspection
|
||||
facilities are available, allowing users to query the list of fields or
|
||||
the value of a specific field at run-time, without prior knowledge of
|
||||
the type.
|
||||
|
||||
Finally, the common denominator of these interfaces is Guile's
|
||||
@dfn{structure} API (@pxref{Structures}). Guile's structures are the
|
||||
low-level building block for all other record APIs. Application writers
|
||||
will normally not need to use it.
|
||||
|
||||
Records created with these APIs may all be pattern-matched using Guile's
|
||||
standard pattern matcher (@pxref{Pattern Matching}).
|
||||
|
||||
|
||||
@node SRFI-9 Records
|
||||
@subsection SRFI-9 Records
|
||||
|
||||
@cindex SRFI-9
|
||||
@cindex record
|
||||
|
||||
SRFI-9 standardizes a syntax for defining new record types and creating
|
||||
predicate, constructor, and field getter and setter functions. In Guile
|
||||
this is the recommended option to create new record types (@pxref{Record
|
||||
Overview}). It can be used with:
|
||||
|
||||
@example
|
||||
(use-modules (srfi srfi-9))
|
||||
@end example
|
||||
|
||||
@deffn {library syntax} define-record-type type @* (constructor fieldname @dots{}) @* predicate @* (fieldname accessor [modifier]) @dots{}
|
||||
@sp 1
|
||||
Create a new record type, and make various @code{define}s for using
|
||||
it. This syntax can only occur at the top-level, not nested within
|
||||
some other form.
|
||||
|
||||
@var{type} is bound to the record type, which is as per the return
|
||||
from the core @code{make-record-type}. @var{type} also provides the
|
||||
name for the record, as per @code{record-type-name}.
|
||||
|
||||
@var{constructor} is bound to a function to be called as
|
||||
@code{(@var{constructor} fieldval @dots{})} to create a new record of
|
||||
this type. The arguments are initial values for the fields, one
|
||||
argument for each field, in the order they appear in the
|
||||
@code{define-record-type} form.
|
||||
|
||||
The @var{fieldname}s provide the names for the record fields, as per
|
||||
the core @code{record-type-fields} etc, and are referred to in the
|
||||
subsequent accessor/modifier forms.
|
||||
|
||||
@var{predicate} is bound to a function to be called as
|
||||
@code{(@var{predicate} obj)}. It returns @code{#t} or @code{#f}
|
||||
according to whether @var{obj} is a record of this type.
|
||||
|
||||
Each @var{accessor} is bound to a function to be called
|
||||
@code{(@var{accessor} record)} to retrieve the respective field from a
|
||||
@var{record}. Similarly each @var{modifier} is bound to a function to
|
||||
be called @code{(@var{modifier} record val)} to set the respective
|
||||
field in a @var{record}.
|
||||
@end deffn
|
||||
|
||||
@noindent
|
||||
An example will illustrate typical usage,
|
||||
|
||||
@example
|
||||
(define-record-type employee-type
|
||||
(make-employee name age salary)
|
||||
employee?
|
||||
(name get-employee-name)
|
||||
(age get-employee-age set-employee-age)
|
||||
(salary get-employee-salary set-employee-salary))
|
||||
@end example
|
||||
|
||||
This creates a new employee data type, with name, age and salary
|
||||
fields. Accessor functions are created for each field, but no
|
||||
modifier function for the name (the intention in this example being
|
||||
that it's established only when an employee object is created). These
|
||||
can all then be used as for example,
|
||||
|
||||
@example
|
||||
employee-type @result{} #<record-type employee-type>
|
||||
|
||||
(define fred (make-employee "Fred" 45 20000.00))
|
||||
|
||||
(employee? fred) @result{} #t
|
||||
(get-employee-age fred) @result{} 45
|
||||
(set-employee-salary fred 25000.00) ;; pay rise
|
||||
@end example
|
||||
|
||||
The functions created by @code{define-record-type} are ordinary
|
||||
top-level @code{define}s. They can be redefined or @code{set!} as
|
||||
desired, exported from a module, etc.
|
||||
|
||||
@unnumberedsubsubsec Non-toplevel Record Definitions
|
||||
|
||||
The SRFI-9 specification explicitly disallows record definitions in a
|
||||
non-toplevel context, such as inside @code{lambda} body or inside a
|
||||
@var{let} block. However, Guile's implementation does not enforce that
|
||||
restriction.
|
||||
|
||||
@unnumberedsubsubsec Custom Printers
|
||||
|
||||
You may use @code{set-record-type-printer!} to customize the default printing
|
||||
behavior of records. This is a Guile extension and is not part of SRFI-9. It
|
||||
is located in the @nicode{(srfi srfi-9 gnu)} module.
|
||||
|
||||
@deffn {Scheme Syntax} set-record-type-printer! name thunk
|
||||
Where @var{type} corresponds to the first argument of @code{define-record-type},
|
||||
and @var{thunk} is a procedure accepting two arguments, the record to print, and
|
||||
an output port.
|
||||
@end deffn
|
||||
|
||||
@noindent
|
||||
This example prints the employee's name in brackets, for instance @code{[Fred]}.
|
||||
|
||||
@example
|
||||
(set-record-type-printer! employee-type
|
||||
(lambda (record port)
|
||||
(write-char #\[ port)
|
||||
(display (get-employee-name record) port)
|
||||
(write-char #\] port)))
|
||||
@end example
|
||||
|
||||
|
||||
@node Records
|
||||
|
|
|
@ -1862,110 +1862,12 @@ procedures easier. It is documented in @xref{Multiple Values}.
|
|||
|
||||
@node SRFI-9
|
||||
@subsection SRFI-9 - define-record-type
|
||||
@cindex SRFI-9
|
||||
@cindex record
|
||||
|
||||
This SRFI is a syntax for defining new record types and creating
|
||||
predicate, constructor, and field getter and setter functions. In
|
||||
Guile this is simply an alternate interface to the core record
|
||||
functionality (@pxref{Records}). It can be used with,
|
||||
predicate, constructor, and field getter and setter functions. It is
|
||||
documented in the ``Compound Data Types'' section of the manual
|
||||
(@pxref{SRFI-9 Records}).
|
||||
|
||||
@example
|
||||
(use-modules (srfi srfi-9))
|
||||
@end example
|
||||
|
||||
@deffn {library syntax} define-record-type type @* (constructor fieldname @dots{}) @* predicate @* (fieldname accessor [modifier]) @dots{}
|
||||
@sp 1
|
||||
Create a new record type, and make various @code{define}s for using
|
||||
it. This syntax can only occur at the top-level, not nested within
|
||||
some other form.
|
||||
|
||||
@var{type} is bound to the record type, which is as per the return
|
||||
from the core @code{make-record-type}. @var{type} also provides the
|
||||
name for the record, as per @code{record-type-name}.
|
||||
|
||||
@var{constructor} is bound to a function to be called as
|
||||
@code{(@var{constructor} fieldval @dots{})} to create a new record of
|
||||
this type. The arguments are initial values for the fields, one
|
||||
argument for each field, in the order they appear in the
|
||||
@code{define-record-type} form.
|
||||
|
||||
The @var{fieldname}s provide the names for the record fields, as per
|
||||
the core @code{record-type-fields} etc, and are referred to in the
|
||||
subsequent accessor/modifier forms.
|
||||
|
||||
@var{predicate} is bound to a function to be called as
|
||||
@code{(@var{predicate} obj)}. It returns @code{#t} or @code{#f}
|
||||
according to whether @var{obj} is a record of this type.
|
||||
|
||||
Each @var{accessor} is bound to a function to be called
|
||||
@code{(@var{accessor} record)} to retrieve the respective field from a
|
||||
@var{record}. Similarly each @var{modifier} is bound to a function to
|
||||
be called @code{(@var{modifier} record val)} to set the respective
|
||||
field in a @var{record}.
|
||||
@end deffn
|
||||
|
||||
@noindent
|
||||
An example will illustrate typical usage,
|
||||
|
||||
@example
|
||||
(define-record-type employee-type
|
||||
(make-employee name age salary)
|
||||
employee?
|
||||
(name get-employee-name)
|
||||
(age get-employee-age set-employee-age)
|
||||
(salary get-employee-salary set-employee-salary))
|
||||
@end example
|
||||
|
||||
This creates a new employee data type, with name, age and salary
|
||||
fields. Accessor functions are created for each field, but no
|
||||
modifier function for the name (the intention in this example being
|
||||
that it's established only when an employee object is created). These
|
||||
can all then be used as for example,
|
||||
|
||||
@example
|
||||
employee-type @result{} #<record-type employee-type>
|
||||
|
||||
(define fred (make-employee "Fred" 45 20000.00))
|
||||
|
||||
(employee? fred) @result{} #t
|
||||
(get-employee-age fred) @result{} 45
|
||||
(set-employee-salary fred 25000.00) ;; pay rise
|
||||
@end example
|
||||
|
||||
The functions created by @code{define-record-type} are ordinary
|
||||
top-level @code{define}s. They can be redefined or @code{set!} as
|
||||
desired, exported from a module, etc.
|
||||
|
||||
@unnumberedsubsubsec Non-toplevel Record Definitions
|
||||
|
||||
The SRFI-9 specification explicitly disallows record definitions in a
|
||||
non-toplevel context, such as inside @code{lambda} body or inside a
|
||||
@var{let} block. However, Guile's implementation does not enforce that
|
||||
restriction.
|
||||
|
||||
@unnumberedsubsubsec Custom Printers
|
||||
|
||||
You may use @code{set-record-type-printer!} to customize the default printing
|
||||
behavior of records. This is a Guile extension and is not part of SRFI-9. It
|
||||
is located in the @nicode{(srfi srfi-9 gnu)} module.
|
||||
|
||||
@deffn {Scheme Syntax} set-record-type-printer! name thunk
|
||||
Where @var{type} corresponds to the first argument of @code{define-record-type},
|
||||
and @var{thunk} is a procedure accepting two arguments, the record to print, and
|
||||
an output port.
|
||||
@end deffn
|
||||
|
||||
@noindent
|
||||
This example prints the employee's name in brackets, for instance @code{[Fred]}.
|
||||
|
||||
@example
|
||||
(set-record-type-printer! employee-type
|
||||
(lambda (record port)
|
||||
(write-char #\[ port)
|
||||
(display (get-employee-name record) port)
|
||||
(write-char #\] port)))
|
||||
@end example
|
||||
|
||||
@node SRFI-10
|
||||
@subsection SRFI-10 - Hash-Comma Reader Extension
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue