Substitution functions and relative octave entry

When \relative is applied to a music expression, it traverses it searching for pitched notes, and modifies the pitches in the order they are found, changing the octave of each pitch according to its octave marks (‘'’ and ‘,’) and the previous pitch. When writing substitution functions, this may lead to the situation that a music expression is ‘relativized’ in a surprising way because the output of the function uses the parameters several times and/or in a different order. Consider this function and how its output reacts to \relative:

simpleAccompaniment =
#(define-music-function
   (bass-1 bass-2 chord) (ly:music? ly:music? ly:music?)
   #{
     $bass-1 $chord $bass-2 $chord
   #})

\relative {
  \clef bass
  \simpleAccompaniment c g <e' g>
  \simpleAccompaniment d g, <f' g>
}

[image of music]

In this example, the output is the same as that of

\relative {
  \clef bass
  c <e' g> g <e' g>
  d <f' g>  g, <f' g>
}

[image of music]

However, this is not the desired output when using the \simpleAccompaniment function. The pitch g, is relative to the first note of the chord that precedes it, <e' g>, although it comes after c in the input. Clearly, the pitches should be made relative according to the order in which they are input when using the function, not in the order they appear in the output of the function. This can be achieved using the make-relative Scheme macro. Its arguments are: a list of variables, a reference expression, and a main music expression. The reference expression is intended to be a mock-up of how the variables were entered in the input. Most of the time, it can be a simple expression made with #{ … #} containing the variables in order. Beware not to make copies in the reference expression (in particular, use ‘#’, not ‘$’). The example above can be fixed using make-relative in this way:

simpleAccompaniment =
#(define-music-function
   (bass-1 bass-2 chord) (ly:music? ly:music? ly:music?)
   (make-relative
    (bass-1 bass-2 chord)
    #{ #bass-1 #bass-2 #chord #}
    #{ $bass-1 $chord $bass-2 $chord #}))

\relative {
  \clef bass
  \simpleAccompaniment c g <e' g>
  \simpleAccompaniment d g, <f' g>
}

[image of music]


LilyPond Notation Reference v2.25.21 (development-branch).