The tendency in classical Lisp is to use lists to represent everything,
and then to browse them “by hand” using
cadr, and co. There are several problems with that style,
notably the fact that it is hard to read, error-prone, and a hindrance
to proper type error reports.
Guix code should define appropriate data types (for instance, using
define-record-type*) rather than abuse lists. In addition, it
should use pattern matching, via Guile’s
(ice-9 match) module,
especially when matching lists (see Pattern Matching in GNU
Guile Reference Manual); pattern matching for records is better done
(guix records), which, unlike
match, verifies field names at macro-expansion time.
When defining a new record type, keep the record type descriptor
(RTD) private (see Records in GNU Guile Reference Manual, for
more on records and RTDs). As an example, the
<package> as the RTD for package records but it
does not export it; instead, it exports a type predicate, a constructor,
and field accessors. Exporting RTDs would make it harder to change the
application binary interface (because code in other modules might be
matching fields by position) and would make it trivial for users to
forge records of that type, bypassing any checks we may have in the
official constructor (such as “field sanitizers”).