Extender LilyPond: A.3.4 Añadir articulaciones a las notas (ejemplo)

### A.3.4 Añadir articulaciones a las notas (ejemplo)

La manera fácil de añadir articulación a las notas es mezclar dos expresiones musicales en un solo contexto, como se explica en Crear contextos. Sin embargo, supongamos que queremos escribir una función musical que lo haga.

Una `$variable` dentro de la notación `#{...#}` es como una `\variable` normal en la notación clásica de LilyPond. Sabemos que

>     { \music -. -> }

no funciona en LilyPond. Podríamos evitar este problema adjuntando la articulación a una nota falsa,

>     { << \music s1*0-.-> }

pero a los efectos de este ejemplo, aprenderemos ahora cómo hacerlo en Scheme. Empezamos examinando nuestra entrada y la salida deseada,

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

Vemos que una nota (`c4`) se representa como una expresión `EventChord`, con una expresión `NoteEvent` en su lista de elementos. Para añadir una articulación de marcato, se debe añadir una expresión `ArticulationEvent` a la propiedad elements de la expresión `EventChord`.

Para construir esta función, empezamos con

>     (define (add-marcato event-chord)
>       "Add a marcato ArticulationEvent to the elements of `event-chord',
>       which is supposed to be an EventChord expression."
>       (let ((result-event-chord (ly:music-deep-copy event-chord)))
>         (set! (ly:music-property result-event-chord 'elements)
>               (cons (make-music 'ArticulationEvent
>                       'articulation-type "marcato")
>                     (ly:music-property result-event-chord 'elements)))
>         result-event-chord))

La primera línea es la forma de definir una función en Scheme: el nombre de la función es `add-marcato`, y tiene una variable llamada `event-chord`. En Scheme, el tipo de variable suele quedar claro a partir de su nombre (¡esto también es una buena práctica en otros lenguajes de programación!)

>     "Add a marcato..."

es una descripción de lo que hace la función. No es estrictamente necesaria, pero de igual forma que los nombres claros de variable, es una buena práctica.

>     (let ((result-event-chord (ly:music-deep-copy event-chord)))

Se usa `let` para declarar las variables locales. Aquí usamos una variable local, llamada `result-event-chord`, a la que le damos el valor `(ly:music-deep-copy event-chord)`. `ly:music-deep-copy` es una función específica de LilyPond, como todas las funciones que comienzan por `ly:`. Se usa para hacer una copia de una expresión musical. Aquí, copiamos `event-chord` (el parámetro de la función). Recuerde que nuestro propósito es añadir un marcato a una expresión `EventChord`. Es mejor no modificar el `EventChord` que se ha dado como argumento, porque podría utilizarse en algún otro lugar.

Ahora tenemos un `result-event-chord`, que es una expresión `NoteEventChord` y es una copia de `event-chord`. Añadimos el marcato a su propiedad de la lista de `'elements`.

>     (set! lugar valor-nuevo)

Aquí, lo que queremos establecer (el ‘lugar’) es la propiedad `'elements` de la expresión `result-event-chord`.

>     (ly:music-property result-event-chord 'elements)

`ly:music-property` es la función que se usa para acceder a las propiedades musicales (los `'elements`, `'duration`, `'pitch`, etc, que vimos en la salida de `\displayMusic` anterior). El nuevo valor es la antigua propiedad `'elements`, con un elemento adicional: la expresión `ArticulationEvent`, que copiamos a partir de la salida de `\displayMusic`,

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

`cons` se usa para añadir un elemento a una lista sin modificar la lista original. Esto es lo que queremos: la misma lista que antes, más la expresión `ArticulationEvent` nueva. El orden dentro de la propiedad `'elements` no es importante aquí.

Finalmente, una vez hemos añadido la articulación marcato a su propiedad `elements`, podemos devolver `result-event-chord`, de ahí la última línea de la función.

Ahora transformamos la función `add-marcato` en una función musical:

>     addMarcato = #(define-music-function (parser location event-chord)
>                                          (ly:music?)
>         "Add a marcato ArticulationEvent to the elements of `event-chord',
>         which is supposed to be an EventChord expression."
>         (let ((result-event-chord (ly:music-deep-copy event-chord)))
>           (set! (ly:music-property result-event-chord 'elements)
>                 (cons (make-music 'ArticulationEvent
>                         'articulation-type "marcato")
>                       (ly:music-property result-event-chord 'elements)))
>           result-event-chord))

Podemos verificar que esta función musical funciona correctamente:

>     \displayMusic \addMarcato c4

#### LilyPond — Extender