Extending LilyPond: 1.3.4 Adding articulation to notes (example)

### 1.3.4 Adding articulation to notes (example)

The easy way to add articulation to notes is to juxtapose two music expressions. However, suppose that we want to write a music function that does this.

A `$variable` inside the `#{…#}` notation is like a regular `\variable` in classical LilyPond notation. We could write

>     { \music -. -> }

but for the sake of this example, we will learn how to do this in Scheme. We begin by examining our input and desired output.

>     %  input
>     \displayMusic c4
>     ===>
>     (make-music
>       'NoteEvent
>       'duration
>       (ly:make-duration 2 0 1/1)
>       'pitch
>       (ly:make-pitch -1 0 0))))
>     =====
>     %  desired output
>     \displayMusic c4->
>     ===>
>     (make-music
>       'NoteEvent
>       'articulations
>       (list (make-music
>               'ArticulationEvent
>               'articulation-type
>               "accent"))
>       'duration
>       (ly:make-duration 2 0 1/1)
>       'pitch
>       (ly:make-pitch -1 0 0))

We see that a note (`c4`) is represented as a `NoteEvent` expression. To add an accent articulation, an `ArticulationEvent` expression must be added to the `articulations` property of the `NoteEvent` expression.

To build this function, we begin with

>     (define (add-accent note-event)
>       "Add an accent ArticulationEvent to the articulations of `note-event',
>       which is supposed to be a NoteEvent expression."
>       (set! (ly:music-property note-event 'articulations)
>             (cons (make-music 'ArticulationEvent
>                     'articulation-type "accent")
>                   (ly:music-property note-event 'articulations)))
>       note-event)

The first line is the way to define a function in Scheme: the function name is `add-accent`, and has one variable called `note-event`. In Scheme, the type of variable is often clear from its name. (this is good practice in other programming languages, too!)

>     "Add an accent…"

is a description of what the function does. This is not strictly necessary, but just like clear variable names, it is good practice.

You may wonder why we modify the note event directly instead of working on a copy (`ly:music-deep-copy` can be used for that). The reason is a silent contract: music functions are allowed to modify their arguments: they are either generated from scratch (like user input) or are already copied (referencing a music variable with ‘`\name`’ or music from immediate Scheme expressions ‘`$(…)`’ provides a copy). Since it would be inefficient to create unnecessary copies, the return value from a music function is not copied. So to heed that contract, you must not use any arguments more than once, and returning it counts as one use.

In an earlier example, we constructed music by repeating a given music argument. In that case, at least one repetition had to be a copy of its own. If it weren’t, strange things may happen. For example, if you use `\relative` or `\transpose` on the resulting music containing the same elements multiple times, those will be subjected to relativation or transposition multiple times. If you assign them to a music variable, the curse is broken since referencing ‘`\name`’ will again create a copy which does not retain the identity of the repeated elements.

Now while the above function is not a music function, it will normally be used within music functions. So it makes sense to heed the same contract we use for music functions: the input may be modified for producing the output, and the caller is responsible for creating copies if it still needs the unchanged argument itself. If you take a look at LilyPond’s own functions like `music-map`, you’ll find that they stick with the same principles.

Where were we? We now have a `note-event` we may modify, not because of using `ly:music-deep-copy` but because of a long-winded explanation. We add the accent to its `'articulations` list property.

>     (set! place new-value)

Here, what we want to set (the ‘place’) is the `'articulations` property of `note-event` expression.

>     (ly:music-property note-event 'articulations)

`ly:music-property` is the function used to access music properties (the `'articulations`, `'duration`, `'pitch`, etc, that we see in the `\displayMusic` output above). The new value is the former `'articulations` property, with an extra item: the `ArticulationEvent` expression, which we copy from the `\displayMusic` output,

>     (cons (make-music 'ArticulationEvent
>             'articulation-type "accent")
>           (ly:music-property result-event-chord 'articulations))

`cons` is used to add an element to the front of a list without modifying the original list. This is what we want: the same list as before, plus the new `ArticulationEvent` expression. The order inside the `'articulations` property is not important here.

Finally, once we have added the accent articulation to its `articulations` property, we can return `note-event`, hence the last line of the function.

Now we transform the `add-accent` function into a music function (a matter of some syntactic sugar and a declaration of the type of its argument).

>     addAccent = #(define-music-function (note-event) (ly:music?)
>       "Add an accent ArticulationEvent to the articulations of `note-event',
>       which is supposed to be a NoteEvent expression."
>       (set! (ly:music-property note-event 'articulations)
>             (cons (make-music 'ArticulationEvent
>                     'articulation-type "accent")
>                   (ly:music-property note-event 'articulations)))
>       note-event)

We then verify that this music function works correctly:

>     \displayMusic \addAccent c4

#### LilyPond — Extending v2.22.2 (stable-branch).