record.texi 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. @node Records
  2. @section Records
  3. @cindex abstract data types
  4. @cindex opaque data types
  5. Scheme48 provides several different levels of a record facility. Most
  6. programmers will probably not care about the two lower levels; the
  7. syntactic record type definers are sufficient for abstract data types.
  8. @cindex defining record types
  9. @cindex record types, defining
  10. @stindex define-record-types
  11. @stindex defrecord
  12. @stindex srfi-9
  13. At the highest level, there are two different record type definition
  14. macros. Richard Kelsey's is exported from the @code{defrecord}
  15. structure; Jonathan Rees's is exported from @code{define-record-types}.
  16. They both export a @code{define-record-type} macro and the same
  17. @code{define-record-discloser} procedure; however, the macros are
  18. dramatically different. Scheme48 also provides [SRFI 9], which is
  19. essentially Jonathan Rees's record type definition macro with a slight
  20. syntactic difference, in the @code{srfi-9} structure. Note, however,
  21. that @code{srfi-9} does not export @code{define-record-discloser}. The
  22. difference between Jonathan Rees's and Richard Kelsey's record type
  23. definition macros is merely syntactic convenience; Jonathan Rees's more
  24. conveniently allows for arbitrary naming of the generated variables,
  25. whereas Richard Kelsey's is more convenient if the naming scheme varies
  26. little.
  27. @subsection Jonathan Rees's @code{define-record-type} macro
  28. @deffn syntax define-record-type
  29. @lisp
  30. (define-record-type @var{record-type-name} @var{record-type-variable}
  31. (@var{constructor} @var{constructor-argument} @dots{})
  32. [@var{predicate}]
  33. (@var{field-tag} @var{field-accessor} [@var{field-modifier}])
  34. @dots{})@end lisp
  35. This defines @var{record-type-variable} to be a record type descriptor.
  36. @var{Constructor} is defined to be a procedure that accepts the listed
  37. field arguments and creates a record of the newly defined type with
  38. those fields initialized to the corresponding arguments.
  39. @var{Predicate}, if present, is defined to be the disjoint (as long as
  40. abstraction is not violated by the lower-level record interface) type
  41. predicate for the new record type. Each @var{field-accessor} is
  42. defined to be a unary procedure that accepts a record type and returns
  43. the value of the field named by the corresponding @var{field-tag}.
  44. Each @var{field-modifier}, if present, is defined to be a binary
  45. procedure that accepts a record of the new type and a value, which it
  46. assigns the field named by the corresponding @var{field-tag} to. Every
  47. @var{constructor-argument} must have a corresponding @var{field-tag},
  48. though @var{field-tag}s that are not used as arguments to the record
  49. type's constructor are simply uninitialized when created. They should
  50. have modifiers: otherwise they will never be initialized.
  51. It is worth noting that Jonathan Rees's @code{define-record-type} macro
  52. does not introduce identifiers that were not in the original macro's
  53. input form.
  54. For example:
  55. @lisp
  56. (define-record-type pare rtd/pare
  57. (kons a d)
  58. pare?
  59. (a kar)
  60. (d kdr set-kdr!))
  61. (kar (kons 5 3))
  62. @result{} 5
  63. (let ((p (kons 'a 'c)))
  64. (set-kdr! p 'b)
  65. (kdr p))
  66. @result{} b
  67. (pare? (kons 1 2))
  68. @result{} #t
  69. (pare? (cons 1 2))
  70. @result{} #f@end lisp
  71. @end deffn
  72. There is also a variant of Jonathan Rees's @code{define-record-type}
  73. macro for defining record types with fields whose accessors and
  74. modifiers respect @embedref{Optimistic concurrency, optimistic
  75. concurrency} by logging in the current proposal.
  76. @subsection Richard Kelsey's @code{define-record-type} macro
  77. @deffn syntax define-record-type
  78. @lisp
  79. (define-record-type @var{type-name}
  80. (@var{argument-field-specifier} @dots{})
  81. (@var{nonargument-field-specifier} @dots{}))
  82. @var{argument-field-specifier} @returns{}
  83. @var{field-tag} Immutable field
  84. | (@var{field-tag}) Mutable field
  85. @var{nonargument-field-specifier} @returns{}
  86. @var{field-tag} Uninitialized field
  87. | (@var{field-tag} @var{exp}) Initialized with @var{exp}'s value@end lisp
  88. @c Huh? ---> ^^^^^^ -- oh, due to extra @var{}
  89. This defines @code{type/@var{type-name}} to be a record type descriptor
  90. for the newly defined record type, @code{@var{type-name}-maker} to be
  91. a constructor for the new record type that accepts arguments for every
  92. field in the argument field specifier list, @code{@var{type-name}?} to
  93. be the disjoint type predicate for the new record type, accessors for
  94. each field tag @var{field-tag} by constructing an identifier
  95. @code{@var{type-name}-@var{field-tag}}, and modifiers for each argument
  96. field tag that was specified to be mutable as well as each nonargument
  97. field tag. The name of the modifier for a field tag @var{field-tag} is
  98. constructed to be
  99. @code{set-@var{type-name}-@var{field-tag}!}.
  100. Note that Richard Kelsey's @code{define-record-type} macro @emph{does}
  101. concatenate & introduce new identifiers, unlike Jonathan Rees's.
  102. For example, a use of Richard Kelsey's @code{define-record-type} macro
  103. @lisp
  104. (define-record-type pare
  105. (kar
  106. (kdr))
  107. (frob
  108. (mumble 5)))@end lisp
  109. @noindent
  110. is equivalent to the following use of Jonathan Rees's macro
  111. @lisp
  112. (define-record-type pare type/pare
  113. (%pare-maker kar kdr mumble)
  114. pare?
  115. (kar pare-kar)
  116. (kdr pare-kdr set-pare-kdr!)
  117. (frob pare-frob set-pare-frob!)
  118. (mumble pare-mumble set-pare-mumble!))
  119. (define (pare-maker kar kdr)
  120. (%pare-maker kar kdr 5))@end lisp
  121. @end deffn
  122. @subsection Record types
  123. @cindex programmatic record types
  124. @cindex record types, programmatic
  125. @stindex record-types
  126. Along with two general record type definition facilities, there are
  127. operations directly on the record type descriptors themselves, exported
  128. by the @code{record-types} structure. (Record type descriptors are
  129. actually records themselves.)
  130. @deffn procedure make-record-type name field-tags @returns{} record-type-descriptor
  131. @deffnx procedure record-type? object @returns{} boolean
  132. @code{Make-record-type} makes a record type descriptor with the given
  133. name and field tags. @code{Record-type?} is the disjoint type
  134. predicate for record types.
  135. @end deffn
  136. @deffn procedure record-type-name rtype-descriptor @returns{} symbol
  137. @deffnx procedure record-type-field-names rtype-descriptor @returns{} symbol-list
  138. Accessors for the two record type descriptor fields.
  139. @end deffn
  140. @deffn procedure record-constructor rtype-descriptor argument-field-tags @returns{} constructor-procedure
  141. @deffnx procedure record-predicate rtype-descriptor @returns{} predicate-procedure
  142. @deffnx procedure record-accessor rtype-descriptor field-tag @returns{} accessor-procedure
  143. @deffnx procedure record-modifier rtype-descriptor field-tag @returns{} modifier-procedure
  144. Constructors for the various procedures relating to record types.
  145. @code{Record-constructor} returns a procedure that accepts arguments
  146. for each field in @var{argument-field-tags} and constructs a record
  147. whose record type descriptor is @var{rtype-descriptor}, initialized
  148. with its arguments. @code{Record-predicate} returns a disjoint type
  149. predicate for records whose record type descriptor is
  150. @var{rtype-descriptor}. @code{Record-accessor} and
  151. @code{record-modifier} return accessors and modifiers for records
  152. whose record type descriptor is @var{rtype-descriptor} for the given
  153. fields.
  154. @end deffn
  155. @deffn procedure define-record-discloser rtype-descriptor discloser @returns{} unspecific
  156. Defines the method by which records of type @var{rtype-descriptor} are
  157. disclosed (@pxref{Writer}). This is also exported by
  158. @code{define-record-types} and @code{defrecord}.
  159. @end deffn
  160. @deffn procedure define-record-resumer rtype-descriptor resumer @returns{} unspecified
  161. Sets @var{rtype-descriptor}'s record resumer to be @var{resumer}. If
  162. @var{resumer} is @code{#t} (the default), records of this type require
  163. no particular reinitialization when found in @embedref{Suspending and
  164. resuming heap images, dumped heap images}; if @var{resumer} is
  165. @code{#f}, records of the type @var{rtype-descriptor} may not be
  166. dumped in heap images; finally, if it is a procedure, and the heap
  167. image is resumed with the @embedref{Suspending and resuming heap
  168. images, usual image resumer}, it is applied to each record whose
  169. record type descriptor is @var{rtype-descriptor} after the run-time
  170. system has been initialized and before the argument to
  171. @code{usual-resumer} is called.
  172. @end deffn
  173. @stindex records-internal
  174. The @code{records-internal} structure also exports these:
  175. @defvr {record type} :record-type
  176. The record type of record types.
  177. @end defvr
  178. @deffn procedure disclose-record record @returns{} disclosed
  179. This applies @var{record}'s record type descriptor's discloser procedure
  180. to @var{record} to acquire a disclosed representation; @pxref{Writer}.
  181. @end deffn
  182. For expository purposes, the record type record type might have been
  183. defined like so with Jonathan Rees's @code{define-record-type} macro:
  184. @lisp
  185. (define-record-type record-type :record-type
  186. (make-record-type name field-names)
  187. record-type?
  188. (name record-type-name)
  189. (field-names record-type-field-names))@end lisp
  190. @noindent
  191. or like so with Richard Kelsey's @code{define-record-type} macro:
  192. @lisp
  193. (define-record-type record-type
  194. (name field-names)
  195. ())@end lisp
  196. @noindent
  197. Of course, in reality, these definitions would have severe problems
  198. with circularity of definition.
  199. @subsection Low-level record manipulation
  200. @cindex records, low-level access to
  201. @cindex low-level access to records
  202. @stindex records
  203. Internally, records are represented very similarly to vectors, and as
  204. such have low-level operations on them similar to vectors, exported by
  205. the @code{records} structure. Records usually reserve the slot at
  206. index 0 for their record type descriptor.
  207. @strong{Warning:} The procedures described here can be very easily
  208. misused to horribly break abstractions. Use them very carefully, only
  209. in very limited & extreme circumstances!
  210. @deffn procedure make-record length init @returns{} record
  211. @deffnx procedure record elt @dots{} @returns{} record
  212. @deffnx procedure record? object @returns{} boolean
  213. @deffnx procedure record-length record @returns{} integer
  214. @deffnx procedure record-ref record index @returns{} value
  215. @deffnx procedure record-set! record index object @returns{} unspecified
  216. Exact analogues of similarly named vector operation procedures.
  217. @end deffn
  218. @deffn procedure record-type record @returns{} value
  219. This returns the record type descriptor of @var{record}, @ie{} the
  220. value of the slot at index 0 in @var{record}.
  221. @end deffn