Extender LilyPond: A.1.4 Tipos de datos compuestos de Scheme

### A.1.4 Tipos de datos compuestos de Scheme

También existen tipos de datos compuestos en Scheme. Entre los tipos más usados en la programación de LilyPond se encuentran las parejas, las listas, las listas-A y las tablas de hash.

### Parejas

El tipo fundacional de datos compuestos de Scheme es la `pareja`. Como se espera por su nombre, una pareja son dos valores unidos en uno solo. El operador que se usa para formar una pareja se llama `cons`.

    guile> (cons 4 5)
    (4 . 5)
    guile>

Observe que la pareja se imprime como dos elementos rodeados por paréntesis y separados por un espacio, un punto (`.`) y otro espacio. El punto no es un punto decimal, sino más bien un indicador de pareja.

Las parejas también se pueden introducir como valores literales precediéndolos de un carácter de comilla simple o apóstrofo.

    guile> '(4 . 5)
    (4 . 5)
    guile>

Los dos elementos de una pareja pueden ser cualquier valor válido de Scheme:

    guile> (cons #t #f)
    (#t . #f)
    guile> '("bla-bla" . 3.1415926535)
    ("bla-bla" . 3.1415926535)
    guile>

Se puede accede al primero y segundo elementos de la pareja mediante los procedimientos de Scheme `car` y `cdr`, respectivamente.

    guile> (define mipareja (cons 123 "Hola")
    ... )
    guile> (car mipareja)
    123
    guile> (cdr mipareja)
    "Hola"
    guile>

Nota: `cdr` se pronuncia "could-er", según Sussman y Abelson, véase http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-14.html#footnote_Temp_133

### Listas

Una estructura de datos muy común en Scheme es la lista. Formalmente, una lista se define como la lista vacía (representada como `'()`, o bien como una pareja cuyo `cdr` es una lista.

Existen muchas formas de crear listas. Quizá la más común es con el procedimiento `list`:

    guile> (list 1 2 3 "abc" 17.5)
    (1 2 3 "abc" 17.5)

Como se ve, una lista se imprime en la forma de elementos individuales separados por espacios y encerradas entre paréntesis. A diferencia de las parejas, no hay ningún punto entre los elementos.

También se puede escribir una lista como una lista literal encerrando sus elementos entre paréntesis y añadiendo un apóstrofo:

    guile> '(17 23 "fulano" "mengano" "zutano")
    (17 23 "fulano" "mengano" "zutano")

Las listas son una parte fundamental de Scheme. De hecho, Scheme se considera un dialecto de Lisp, donde ‘lisp’ es una abreviatura de ‘List Processing’ (proceso de listas). Todas las expresiones de Scheme son listas.

### Listas asociativas (listas-A)

Un tipo especial de listas son las listas asociativas o listas-A. Se puede usar una lista-A para almacenar datos para su fácil recuperación posterior.

Las listas-A son listas cuyos elementos son parejas. El `car` de cada elemento se llama clave, y el `cdr` de cada elemento se llama valor. El procedimiento de Scheme `assoc` se usa para recuperar un elemento de la lista-A, y `cdr` se usa para recuperar el valor:

    guile> (define mi-lista-a '((1  . "A") (2 . "B") (3 . "C")))
    guile> mi-lista-a
    ((1 . "A") (2 . "B") (3 . "C"))
    guile> (assoc 2 mi-lista-a)
    (2 . "B")
    guile> (cdr (assoc 2 mi-lista-a))
    "B"
    guile>

Las listas-A se usan mucho en LilyPond para almacenar propiedades y otros datos.

### Tablas de hash

Estructuras de datos que se utilizan en LilyPond de forma ocasional. Una tabla de hash es similar a una matriz, pero los índices de la matriz pueden ser cualquier tipo de valor de Scheme, no sólo enteros.

Las tablas de hash son más eficientes que las listas-A si hay una gran cantidad de datos que almacenar y los datos cambian con muy poca frecuencia.

La sintaxis para crear tablas de hash es un poco compleja, pero veremos ejemplos de ello en el código fuente de LilyPond.

    guile> (define h (make-hash-table 10))
    guile> h
    #<hash-table 0/31>
    guile> (hashq-set! h 'key1 "val1")
    "val1"
    guile> (hashq-set! h 'key2 "val2")
    "val2"
    guile> (hashq-set! h 3 "val3")
    "val3"

Los valores se recuperan de las tablas de hash mediante `hashq-ref`.

    guile> (hashq-ref h 3)
    "val3"
    guile> (hashq-ref h 'key2)
    "val2"
    guile>

Las claves y los valores se recuperan como una pareja con `hashq-get-handle`. Ésta es la forma preferida, porque devuelve `#f` si no se encuentra la clave.

    guile> (hashq-get-handle h 'key1)
    (key1 . "val1")
    guile> (hashq-get-handle h 'frob)
    #f
    guile>

Otros idiomas: English, deutsch.

#### LilyPond — Extender