1.2.3 Input variables and Scheme

The input format supports the notion of variables: in the following example, a music expression is assigned to a variable with the name traLaLa.

traLaLa = { c'4 d'4 }

There is also a form of scoping: in the following example, the \layout block also contains a traLaLa variable, which is independent of the outer \traLaLa.

traLaLa = { c'4 d'4 }
\layout { traLaLa = 1.0 }

In effect, each input file is a scope, and all \header, \midi, and \layout blocks are scopes nested inside that toplevel scope.

Both variables and scoping are implemented in the GUILE module system. An anonymous Scheme module is attached to each scope. An assignment of the form:

traLaLa = { c'4 d'4 }

is internally converted to a Scheme definition:

(define traLaLa Scheme value of `')

This means that LilyPond variables and Scheme variables may be freely mixed. In the following example, a music fragment is stored in the variable traLaLa, and duplicated using Scheme. The result is imported in a \score block by means of a second variable twice:

traLaLa = { c'4 d'4 }

#(define newLa (map ly:music-deep-copy
  (list traLaLa traLaLa)))
#(define twice
  (make-sequential-music newLa))


[image of music]

This is actually a rather interesting example. The assignment will only take place after the parser has ascertained that nothing akin to \addlyrics follows, so it needs to check what comes next. It reads # and the following Scheme expression without evaluating it, so it can go ahead with the assignment, and afterwards execute the Scheme code without problem.

LilyPond — Extending v2.23.3 (development-branch).