LilyPond currently hardcodes certain print functions as being able
to be evaluated as 'pure', meaning that they should not result in calls
to set_property, set_object, translate_axis or suicide. This means that,
for example, if one uses a custom stencil function, the Y-extent function
for the grob must be wrapped in an unpure-pure-container in order
to return a non-empty pure_height.
The reading of these hardcoded lists results in difficult-to-maintain code.
For example, several (but not all) flag modification functions are part of
this list, causing spacing inconsistencies in certain regtests.
Using unpure-pure-containers to signify all relationships between unpure and
pure functions and eliminating the lists of pure functions in
define-grobs.scm allows the code base to be more extensible, demanding the
elaboration of unpure-pure relationships in the property-setting phase
(either in define-grobs.scm or in an override) and not using hardcoded lists.
Inversely, this also prevents deep that can creep up when a function
signified as pure turns out not to be. For example, ly:note-head::print,
marked as pure, can be made unpure if its lookup of the style,
duration-log or glyph-name properties trigger vertical alignment
(which results in a call to translate_axis). Thus, users who wish to use
this function as an unpure function now can because it is no longer
hardcoded as pure.