2023-02-27

(sph record)

all vector procedures can be used and vectors have a read/write syntax

description

  • a record in this sense differs from an association list, for example, in that the keys are not stored inside the data-structure, but separately: a "layout" stores the field names and indices of field values
  • requiring to use a layout object might seem unnecessary, but most other record implementations share this trait because it follows from what the word "record" usually means in scheme
  • because field-names/keys are not stored or otherwise encoded with every record instance, they use less memory than alists
  • because accessor procedures do not need to make extra searches for the positions of the field-values like comparing the keys of alist pairs, or hashing in hashtables, field access can be faster and the performance is nearly the same as for vectors
  • the library does support getting/setting field values with symbol names instead of accessor/setter procedures, but this is slower than with hashtables
  • it is possible to define record-layouts procedurally with using the alternative bindings to "define-record"

upsides

  • access vector fields using symbolic names
  • low memory usage per record element
  • no special data type, records are standard vectors

downsides

  • in this implementation, the creation of record instances is a bit slower than vector creation
  • the complexity of having record-layouts, accessors, setters and having to pass the layout to some procedures

theoretical comparison

  • memory usage: vector = sph-record < hashtable
  • operations for creation: vector < sph-record < hashtable
  • operations for typical field access: vector < sph-record < hashtable
  • operations for integer index access: vector = sph-record

examples

define a record type

(define-record my-record a b c)
(define-record my-other-record (a my-a-accessor-name my-a-setter-name) b (c my-c-accessor-name))

create record instances

(define one-element (record my-record 1 2 3))
(define another-element (record my-record #f "b"))
(define a-third-element (record my-record))

access and modify instances

(my-record-b one-element)
(my-record-c-set! one-element 4)
(my-record-c-set! another-element "custom-value")

bindings

define-record

unquoted-symbol/(field-name [accessor-identifier setter-identifier])

with three fields named "a" "b" and "c"

(define-record my-record a b c)

this implicitly defines the procedures my-record-a, my-record-b, my-record-c to access record values for the corresponding fields for any record instance, and it also defines the procedures my-record-a-set!, my-record-b-set!, my-record-c-set! to set record values

different names for accessors and setters

(define-record my-record (a my-a-accessor-name my-a-setter-name) b (c my-c-accessor-name))

here "c" gets a custom accessor name but the default setter "my-record-c-set!", "a" gets a custom accessor and setter name, and "b" gets the default accessor and setter name

these record libraries regard records as something more complicated