B.8 Contenedores Unpure-pure (Extender LilyPond)

### B.8 Contenedores Unpure-pure

Nota: Si bien esta subsección refleja la situación actual, el ejemplo dado es irrelevante y no muestra ningún efecto.

Los contenedores unpure-pure son útiles para sobreescribir los cálculos de espaciado en Y-axis, el eje Y (específicamente `Y-offset` y `Y-extent`) con una función de Scheme en lugar de un valor literal, como un número o una pareja de números.

Para determinados objetos gráficos, las dimensiones verticales `Y-extent` están basadas en la propiedad `stencil` (sello): la sobreescritura de la propiedad sello de uno de estos objetos necesitaría otra sobreescritura de `Y-extent` con un contenedor unpure-pure. Cuando una función sobreescribe el desplazamiento `Y-offset` y/o las dimensiones verticales `Y-extent`, se supone que ello dispara los álculos de los saltos de línea demasiado pronro durante la compilación. Por ello la función no se evalúa en absoluto (devolviendo por lo general un valor de ‘`0`’ o de ‘`'(0 . 0)`’) lo que puede dar colisiones como resultado. Una función ‘pure’ no afecta a las propiedades, los objetos se suicidan y por tanto siempre tendrán evaluado correctamente su valor relacionado con el eje Y.

En este momento existen aproximadamente 30 funciones que ya se conbsideran ‘pure’ y los contenedores Unpure-pure son una manera de establecer como ‘pure’ funciones que no están en esta lista. La función ‘pure’ se evalúa antes de cualquier salto de línea y así el espaciado horizontal se puede ajustar ‘a tiempo’. La función ‘unpure’ se evalúa entonces después del salto de línea.

Nota: Dado que es difícil saber en todo momento qué funciones están en esta lista, recomendamos que cualquier función ‘pure’ que usted cree, no utilicen los objetos gráficos `Beam` ni `VerticalAlignment`.

Un contenedor unpure-pure se construye como sigue:

    (ly:make-unpure-pure-container f0 f1)

donde `f0` es una función que toma n argumentos (n >= 1) y el primer argumento debe ser siempre el grob. Esta es la función que da el resultado real. f1 es la función que se está etiquetando como ‘pure’ que toma n + 2 argumentos. De nuevo, el primer argumento siempre debe ser el grob, pero el segundo y el tercero son los argumentos de ‘inicio’ y ‘fin’.

inicio y fin son, a todos los efectos, valores mudos que solo tienen importancia para los objetos de extensión (`Spanners` como `Hairpin`, reguladores, o `Beam`, barras), que pueden devolver diferentes estimaciones de altura basadas en una columna de inicio y de final.

El resto son los otros argumentos para la primera función (que pueden no ser ninguno si n = 1).

Los resultados de la segunda función se usan como aproximación del valor requerido cuando se usa después por parte de la primera función para obtener el valor real que se usa entonces para el ajuste fino mucho tiempo después, durante el proceso de espaciado.

>     #(define (square-line-circle-space grob)
>     (let* ((pitch (ly:event-property (ly:grob-property grob 'cause)
>                                      'pitch))
>           (notename (ly:pitch-notename pitch)))
>      (if (= 0 (modulo notename 2))
>          (make-circle-stencil 0.5 0.0 #t)
>          (make-filled-box-stencil '(0 . 1.0)
>                                   '(-0.5 . 0.5)))))

>     squareLineCircleSpace = {
>       \override NoteHead.stencil = #square-line-circle-space
>     }

>     smartSquareLineCircleSpace = {
>       \squareLineCircleSpace
>       \override NoteHead.Y-extent =
>        #(ly:make-unpure-pure-container
>           ly:grob::stencil-height
>           (lambda (grob start end) (ly:grob::stencil-height grob)))
>     }

>     \new Voice \with { \remove Stem_engraver }
>     \relative c'' {
>       \squareLineCircleSpace
>       cis4 ces disis d
>       \smartSquareLineCircleSpace
>       cis4 ces disis d
>     }

En el primer compás, sin un contenedor unpure-pure, el motor de espaciado no conoce la anchura de la cabeza de la nota ydeja que choque con las alteraciones accidentales. En el segundo compás, con contenedores unpure-pure, el motor de espaciado conoce el ancho de las cabezas de nota y evita la colisión alargando la línea adecuadamente.

Normalmente, para cálculos sencillos se pueden usar funciones casi idénticas para las dos partes ‘unpure’ y ‘pure’ , solo cambiando el número de los argumentos que se pasan a, y el ámbito de, la función. Este ejemplo de utilización es lo bastante frecuente como para que `ly:make-unpure-pure-container` construya una segunda función de forma predeterminada cuando se llama con solo un argumento de función.

Nota: Si una función se etiqueta como ‘pure’ y después resulta que no lo es, los resultados pueden ser inesperados.

#### Extender LilyPond v2.26.0 (stable-branch).

- Appendix A Tutorial de Scheme
  - A.1 Introducción a Scheme
    - A.1.1 Cajón de arena de Scheme
    - A.1.2 Variables de Scheme
    - A.1.3 Tipos de datos simples de Scheme
    - A.1.4 Tipos de datos compuestos de Scheme
      - Parejas
      - Listas
      - Listas asociativas (listas-A)
      - Tablas de hash
    - A.1.5 Cálculos en Scheme
    - A.1.6 Procedimientos de Scheme
      - Definir procedimientos
      - Predicados
      - Valores de retorno
    - A.1.7 Condicionales de Scheme
      - if
      - cond
  - A.2 Scheme dentro de LilyPond
    - A.2.1 Sintaxis del Scheme de LilyPond
    - A.2.2 Variables de LilyPond
    - A.2.3 Depuración del código de Scheme
    - A.2.4 Variables de entrada y Scheme
    - A.2.5 Importación de Scheme dentro de LilyPond
    - A.2.6 Propiedades de los objetos
    - A.2.7 Variables de LilyPond compuestas
      - Desplazamientos
      - Fracciones
      - Dimensiones
      - Listas-A de propiedades
      - Cadenas de listas-A
    - A.2.8 El modelo de caja de LilyPond
    - A.2.9 Representación interna de la música
  - A.3 Construir funciones complicadas
    - A.3.1 Una primera aproximación (ejemplo)
    - A.3.2 Presentación de las expresiones musicales
    - A.3.3 Propiedades musicales
    - A.3.4 Duplicar una nota con ligaduras (ejemplo)
    - A.3.5 Añadir articulaciones a las notas (ejemplo)
- B Interfaces para programadores
  - B.1 Bloques de código de LilyPond
  - B.2 Funciones de Scheme
    - B.2.1 Definición de funciones de Scheme
    - B.2.2 Uso de las funciones de Scheme
    - B.2.3 Funciones de Scheme vacías
  - B.3 Funciones musicales
    - B.3.1 Definiciones de funciones musicales
    - B.3.2 Uso de las funciones musicales
    - B.3.3 Funciones de sustitución sencillas
    - B.3.4 Funciones de sustitución intermedias
    - B.3.5 Matemáticas dentro de las funciones
    - B.3.6 Funciones sin argumentos
    - B.3.7 Funciones musicales vacías
  - B.4 Funciones de eventos
  - B.5 Funciones de marcado
    - B.5.1 Construcción de elementos de marcado en Scheme
    - B.5.2 Cómo funcionan internamente los elementos de marcado
    - B.5.3 Definición de una instrucción de marcado nueva
      - Sintaxis de la definición de instrucciones de marcado
      - Acerca de las propiedades
      - Un ejemplo completo
      - Adaptación de instrucciones incorporadas
      - Convertir elementos de marcado en cadenas
    - B.5.4 Definición de nuevas instrucciones de lista de marcado
  - B.6 Contextos para programadores
    - B.6.1 Evaluación de contextos
    - B.6.2 Ejecutar una función sobre todos los objetos de la presentación
  - B.7 Funciones de callback
  - B.8 Contenedores Unpure-pure
  - B.9 Trucos difíciles
- C Interfaces de Scheme de LilyPond
- Appendix D GNU Free Documentation License
- Appendix E Índice