RECORD-TYPE-NAME(3scm)

πŸ“¦ version 0-unstable-2024-02, in nixpkgs unstable

πŸ’… make-record-type-descriptor(3scm) β€” the Scheme Programmer's Manual, but make it cute πŸŽ€

okay bestie so this page lives in the Scheme Programmer's Manual and it's literally the whole ~record type~ saga β€” building them, checking them, poking at them. it's giving backstage pass to the record system πŸ’–


✨ LIBRARY ✨

(import (rnrs))                     ;R6RS
(import (rnrs records procedural))  ;R6RS
(import (rnrs records inspection))  ;R6RS

three ways in, take your pick 🫢


πŸ¦‹ SYNOPSIS πŸ¦‹

; Procedural library
(make-record-type-descriptor name parent uid sealed? opaque? fields)
(record-type-descriptor? obj)

; Inspection library
(record-field-mutable? rtd number)
(record-type-field-names rtd)
(record-type-generative? rtd)
(record-type-name rtd)
(record-type-opaque? rtd)
(record-type-parent rtd)
(record-type-sealed? rtd)
(record-type-uid rtd)

🌸 DESCRIPTION 🌸

make-record-type-descriptor returns a record-type descriptor (an rtd for the girlies in the know πŸ’…) β€” and this rtd represents a record type that's distinct from every built-in type AND every other record type. main character energy, no cap ✨

πŸŽ€ Record names πŸŽ€

the name argument must be a symbol. it names the record type, and it's intended purely for informational purposes β€” it may be used for printing by the underlying Scheme system. so it's basically the name tag at the party, not the bouncer 🌈

🧚 Record inheritance 🧚

the parent argument must be either #f or an rtd. if it's an rtd, then the returned record type extends the record type that parent represents. and β€” heads up β€” an exception with condition type &assertion(7scm) is raised if parent is sealed. sealed means no kids, periodt πŸ’€

⭐ Unique identifiers ⭐

the uid argument must be either #f or a symbol.

  • if uid is a symbol, the record-creation operation is nongenerative β€” a new record type gets created only if no previous call to make-record-type-descriptor was made with the uid.
  • if uid is #f, the record-creation operation is generative β€” a new record type is created even if a previous call to make-record-type-descriptor was made with the same arguments.

and okay this is the part you gotta memorize for the exam: if make-record-type-descriptor is called twice with the same uid symbol, then all of these must line up between the two calls πŸ‘‡

  • the parent arguments must be eqv?(3scm)
  • the fields arguments equal?(3scm)
  • the sealed? arguments boolean-equivalent (both #f or both true)
  • the opaque? arguments boolean-equivalent if the parents are not opaque

if these conditions are not met, an exception with condition type &assertion(7scm) is raised when the second call occurs. if they are met, the second call returns β€” without creating a new record type β€” the same record-type descriptor (in the sense of eqv?(3scm)) as the first call. same rtd, no dupe, slay πŸ’…

πŸ”₯ Sealed records πŸ”₯

the sealed? flag must be a boolean. if true, the returned record type is sealed β€” meaning it cannot be used as a parent. sorry babe, closed for adoption 🚫

πŸ™ˆ Opaque records πŸ™ˆ

the opaque? flag must be a boolean. if true, the record type is opaque. and the consequences are real:

  • if passed an instance of the record type, record?(3scm) returns #f
  • moreover, if record-rtd(3scm) is called with an instance of the record type, an exception with condition type &assertion(7scm) is raised

the record type is also opaque if an opaque parent is supplied. if opaque? is #f and an opaque parent is not supplied, the record is not opaque. genetics, basically 🧬

πŸ“ Record fields πŸ“

the fields argument must be a vector of field specifiers. each field specifier must be either:

  • a list of the form (mutable name), or
  • a list of the form (immutable name)

each name must be a symbol and names the corresponding field of the record type. the names need not be distinct β€” yes you can have twins, it's fine ✨

a field identified as mutable may be modified. whereas β€” and this is the dramatic part 😭 β€” when a program attempts to obtain a mutator with record-mutator(3scm) for a field identified as immutable, an exception with condition type &assertion(7scm) is raised.

where field order is relevant (e.g., for record construction and field access), the fields are considered ordered as specified, although no particular order is required for the actual representation of a record instance.

the specified fields are added to the parent fields, if any, to determine the complete set of fields of the returned record type. stacked like pancakes πŸ₯ž

if fields is modified after make-record-type-descriptor has been called, the effect on the returned rtd is unspecified. so like… don't πŸ‘€

πŸ‘‘ Generative records πŸ‘‘

a generative record-type descriptor created by a call to make-record-type-descriptor is not eqv?(3scm) to any record-type descriptor (generative or nongenerative) created by another call to make-record-type-descriptor. a generative record-type descriptor is eqv?(3scm) only to itself, i.e.:

(eqv? rtd1 rtd2)  iff  (eq? rtd1 rtd2)

also, two nongenerative record-type descriptors are eqv?(3scm) iff they were created by calls to make-record-type-descriptor with the same uid arguments. iykyk 🫢


the following procedures are used to inspect the rtd πŸ”

🌟 record-type-name

returns the name of the record-type descriptor rtd.

🌟 record-type-parent

returns the parent of the record-type descriptor rtd, or #f if it has none.

🌟 record-type-uid

returns the uid of the record-type descriptor rtd, or #f if it has none.

an implementation may assign a generated uid to a record type even if the type is generative β€” so the return of a uid does not necessarily imply that the type is nongenerative. plot twist πŸ’€

🌟 record-type-generative?

returns #t if rtd is generative, and #f if not.

🌟 record-type-sealed?

returns #t if rtd is sealed, and #f if not.

🌟 record-type-opaque?

returns #t if rtd is opaque, and #f if not.

🌟 record-type-field-names

returns a vector of symbols naming the fields of the type represented by rtd β€” not including the fields of parent types β€” where the fields are ordered as in the fields argument.

the returned vector may be immutable. if the returned vector is modified, the effect on rtd is unspecified. hands off πŸ‘

🌟 record-field-mutable?

returns #t if the field specified by k of the type represented by rtd is mutable, and #f if not. the k argument is described in record-accessor(3scm).


πŸ’– RETURN VALUES πŸ’–

  • make-record-type-descriptor β€” returns a single value; a record type descriptor.
  • record-type-field-names β€” returns a single value; a vector of symbols.
  • record-type-name β€” returns a single value; a symbol.
  • record-type-parent β€” returns a single value; a record type descriptor or #f.
  • record-type-uid β€” returns a single value; a symbol or #f.
  • record-type-descriptor?, record-type-opaque?, record-type-sealed?, record-type-generative?, record-field-mutable? β€” these procedures return a single value; a boolean.

🌈 EXAMPLES 🌈

okay this example ate, fr fr:

(define rtd-user
  (make-record-type-descriptor
    'user #f #f #f #f
    '#((immutable login) (immutable realname))))
(define rcd-user
  (make-record-constructor-descriptor
    rtd-user #f
    (lambda (p)
      (lambda (login realname)
        (p login realname)))))
(define make-user (record-constructor rcd-user))

(make-user 'lain "Lain Iwakura")
  => #[user login: lain realname: "Lain Iwakura"]

literally iconic πŸ‘‘


🫢 APPLICATION USAGE 🫢

the syntactic layer is more commonly used in applications β€” see define-record-type(7scm). however, the procedural layer is needed to create new record types at runtime. the inspection layer is used to create, e.g., record printers.

a program that intends to use a record type descriptor to create a record also needs to create a record constructor descriptor with make-record-constructor-descriptor(7scm). two-step process bestie, don't skip step one πŸŽ€

users are encouraged to use symbol names constructed using the UUID namespace (for example, using the record-type name as a prefix) for the uid argument. cute AND collision-free ✨


πŸ¦‹ COMPATIBILITY πŸ¦‹

these procedures are unique to the R6RS record system. equivalent procedures can be found in SRFI-237.


πŸ’€ ERRORS πŸ’€

this procedure can raise exceptions with the following condition types:

  • &assertion (R6RS) β€” the wrong number of arguments was passed, or an argument was outside its domain. the requirements on the arguments are described above.

πŸ” SEE ALSO πŸ”

define-record-type(7scm), make-record-constructor-descriptor(7scm), record-predicate(3scm), record-accessor(3scm), record-mutator(3scm)


⭐ STANDARDS ⭐

R6RS


🌸 HISTORY 🌸

these procedures first appeared in R6RS as part of the new record system.


πŸŽ€ AUTHORS πŸŽ€

this page is part of the scheme-manpages project. it includes materials from the RnRS documents. more information can be found at https://github.com/schemedoc/manpages/.


and that's the whole page diva πŸ’… this came from the scheme-manpages project (vibes: immaculate, source: the RnRS documents), dated 2023-08-02, and it's signed make-rec...escriptor(3scm) β€” go build some records, you got this 🫢✨🌷

πŸ“¦ where this page comes from