[ << Programming work ] | [Top][Contents] | [ Release work >> ] |
[ < Understanding pure properties ] | [ Up : Understanding pure properties ] | [ Writing a pure function > ] |
10.13.1 Purity in LilyPond
Pure properties in LilyPond are properties that do not have any ‘side effects’. That is, looking up a pure property should never result in calls to the following functions:
-
set_property
-
set_object
-
suicide
This means that, if the property is calculated via a callback, this callback
must not only avoid the functions above but make sure that any functions
it calls also avoid the functions above. Also, to date in LilyPond, a pure
function will always return the same value before line breaking (or, more
precisely, before any version of break_into_pieces
is called). This
convention makes it possible to cache pure functions and be more flexible
about the order in which functions are called. For example; Stem.length
has
a pure property that will never trigger one of the functions listed
above and will always return the same value before line breaking,
independent of where it is called. Sometimes, this will be the actual length
of the Stem. But sometimes it will not. For example; stem that links up
with a beam will need its end set to the Y position of the beam at the stem’s
X position. However, the beam’s Y positions can only be known after the score
is broken up in to several systems (a beam that has a shallow slope on a
compressed line of music, for example, may have a steeper one on an
uncompressed line). Thus, we only call the impure version of the properties
once we are absolutely certain that all of the parameters needed to
calculate their final value have been calculated. The pure version provides a
useful estimate of what this Stem length (or any property) will be, and
the art of creating good pure properties is trying to get the estimation
as close to the actual value as possible.
Of course, like Gregory Peck and Tintin, some Grobs will have properties that will always be pure. For example, the height of a note-head in not-crazy music will never depend on line breaking or other parameters decided late in the typesetting process. Inversely, in rare cases, certain properties are difficult to estimate with pure values. For example, the height of a Hairpin at a certain cross-section of its horizontal span is difficult to know without knowing the horizontal distance that the hairpin spans, and LilyPond provides an over-estimation by reporting the pure height as the entire height of the Hairpin.
Purity, like for those living in a convent, is more like a contract than an a priori. If you write a pure-function, you are promising the user (and the developer who may have to clean up after you) that your function will not be dependent on factors that change at different stages of the compilation process (compilation of a score, not of LilyPond).
One last oddity is that purity, in LilyPond, is currently limited exclusively to things that have to do with Y-extent and positioning. There is no concept of ‘pure X’ as, by design, X is always the independent variable (i.e., from column X1 to column X2, what will be the Y height of a given grob). Furthermore, there is no purity for properties like color, text, and other things for which a meaningful notion of estimation is either not necessary or has not yet been found. For example, even if a color were susceptible to change at different points of the compilation process, it is not clear what a pure estimate of this color would be or how this pure color could be used. Thus, in this document and in the source, you will see purity discussed almost interchangeably with Y-axis positioning issues.
[ << Programming work ] | [Top][Contents] | [ Release work >> ] |
[ < Understanding pure properties ] | [ Up : Understanding pure properties ] | [ Writing a pure function > ] |