How to prevent sharing of music expressions

When writing music functions, it is important to abide by a rule: the same music expressions must not be shared in several places. As an example, here is a problematic function:

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

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

[image of music]

The problem with this function becomes clear if the result is transposed:

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

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

[image of music]

While the bass notes are correct, the chord is not transposed properly – in fact, it is being transposed twice. The reason for this is that the music expression chord was used twice in the result of the function, without copying it. Functions such as \transpose modify the music object directly (in the case of \transpose, the pitches are changed). If the same music object is reused, modifications made in one place where it is used affect both places, since they hold the same object. In this case, \transpose encounters the object twice and transposes it twice.

One way to fix this function is to use ‘$’ instead of ‘#’ to reference the variables, which makes a copy. The difference between ‘#’ and ‘$’ is detailed in LilyPond Scheme syntax.

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

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

[image of music]


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