# (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 * [rnrs records](https://www.gnu.org/software/guile/manual/html_node/rnrs-records-syntactic.html#rnrs-records-syntactic) has (rnrs records syntactic) and (rnrs records procedural) * [srfi-9](https://www.gnu.org/software/guile/manual/html_node/SRFI_002d9-Records.html#SRFI_002d9-Records)