Why Scheme?

The Scheme language is a derivative of the ancestral language Lisp. It was originally designed to serve in MIT courses. From this history stems an aim at consistency and simplicity, if not minimalism.

LilyPond uses Scheme as an extension language. This is a common technique. The core of the program is written in a compiled language, which in the case of LilyPond is C++. This core interacts with an interpreted language, in our case Scheme. “Compiled language” here means that the program is translated once and for all into machine code. While that makes it very fast, it also freezes its functionality, since extending the program must be done by modifying its sources and going through the pain of recompiling it. On the other hand, with an interpreted language, the code is understood as it is read, without compilation. This brings the possibility to insert it in the LilyPond file and to modify it very easily, with the modifications immediately taking effect on the file, and without setting up a compilation environment.

In fact, LilyPond does not merely use Scheme as an extension language, but also as a programming language for a large part of its internals. This is what gives it a breathtaking level of extensibility. From the user point of view, this has many applications, ranging from more convenient ad-hoc input methods to encoding completely novel graphical notations specific to a composer.

Without going into such advanced use cases, knowing a bit of Scheme is a useful skill for any LilyPond user considering that Scheme fragments are embedded literally everywhere in typical LilyPond input. Some examples:

title = ##f
\override NoteHead.style = #'cross
\shape #'((0 . 0) (0.1 . 0.3) (0.1 . 0.5) (0 . 1.0)) Slur
\override Staff.TupletBracket.direction = #DOWN

Keep in mind that there is no single implementation of Scheme. In fact, there are dozens. Each comes with its own strengths and peculiarities. The implementation used in LilyPond is Guile because it is the official extension language of the GNU project, to which LilyPond also belongs. The name “Guile” is an acronym for “GNU Ubiquitous Intelligent Language for Extensions”. (The “Ubiquitous” part amounts to wishful thinking. About “Intelligent”, I leave it up to the reader to judge by themselves.)

Please also bear in mind that the version of Guile embedded in LilyPond is generally not the latest version of Guile. At the time of this writing, the latest stable Guile release series is Guile 3.0 On the other hand, LilyPond’s stable release series, the 2.22 series, uses Guile 1.8, while the 2.23 unstable release series uses Guile 2.2 exclusively starting with LilyPond 2.23.7. The manual for Guile 1.8 can be found at https://www.gnu.org/software/guile/docs/docs-1.8/guile-ref/. That of Guile 2.2 is at https://www.gnu.org/software/guile/docs/docs-2.2/guile-ref/. In all cases, you can check your version of Guile by compiling the LilyPond input #(display (version)), which prints the Guile version in the log.