14.3. Listas, Listas Y Más Listas

Te hemos entrenado en variables y funciones, y ahora, entramos en el lúgubre pantano de las listas Scheme.

Definiendo Una Lista

Antes hablamos más sobre las listas, es necesario que sepas la diferencia entre valores atómicos y listas..

Ya has visto los valores atómicos cuando inicializamos variables en la lección anterior. Un valor atómico es un valor simple. Así, por ejemplo, podemos asignar a la variable "x" el valor simple de 8 en la declaración siguiente:

        (let* ( (x 8) ) x)
      

(Añadimos la expresión x al final para imprimir el valor asignado a  x-- normalmente, no necesitarás hacer esto. Nota como let* opera justo como una función: El valor de la última declaración es el valor devuelto).

Una variable puede, tambien, referirse a una lista de valores, casi como un valor simple. Para asignar a la variable x , la lista de valores 1, 3, 5, tecleamos:

        (let* ( (x '(1 3 5))) x)
      

Intenta teclear ambas declaraciones en la Consola Script-Fu y verás como contesta. Cuando tecleas la primera declaración, responde con el resultado:

        8
      

Cuando tecleas la otra declaración, responde con el siguiente resultado:

        (1 3 5)
      

Cuando responde con el valor 8 está informandote que x contiene el valor atómico 8. Cuando responde con  (1 3 5), Entonces, está informandote que x no contiene un valor simple, sino una lista de valores. Nota que no hay comillas en nuestra declaración o en la asignación de la lista, ni  en el resultado impreso.

La sintaxis para definir una lista es:

         '(a b c)
      

donde a, b, y c son literales. Usamos el apóstrofe (') para indicar eso que lo que sigue entre paréntesis es una lista de valores literales, casí como una función o expresión.

Una lista vacia puede ser definida como:

        '()
      

o simplemente:

        ()
      

Las listas pueden contener valores atómicos, tanto como otras listas:

        (let*
           (
                (x
                   '("The Gimp" (1 2 3) ("is" ("great" () ) ) )
                )
            )

            x
         )
      

Nota  que después del primer apóstrofe, no necesitas usar un apóstrofe cuando definas las listas internas. Adelante, copia la declaración en la Consola Script-Fu y mira que devuelve.

Notarás que el resultado devuelto no es una lista de simples valores atómicos; casí es una lista de un literal("The Gimp"), la lista (1 2 3), etc.

Como Pensar De Las Listas

Es útil pensar de las listas como compuestas de una "cabeza" y una "cola". La cabeza es el primer elemento de la lista, la cola es el resto de la lista. Verás porque esto es importante cuando tratemos como añadir listas y como acceder elementos en la lista.

Creando Listas Mediante Concatenación (La Función cons)

Una de las funciones más comunes que encontrarás es la función cons. Toma un valor y prepends it to el segundo argumento, una lista. En la sección previa, sugerí que pienses de una lista  como que se está componiendo de un elemento (la cabeza) y el resto de la lista (la cola). Es, exactamente, como cons funciona -- añade un elemento a la cabeza de la lista. Puedes crear una lista como sigue:

        (cons 1 '(2 3 4) )
      

El resultado es la lista (1 2 3 4).

Tambien, podrías crear una lista con un elemento:

        (cons 1 () )
      

Puedes usar, previamente, variables declaradas en lugar de literales,  como espararías.

Definiendo Una Lista Usando La Función list

Para definir una lista compuesta de literales o previamente variables declaradas, usa la función list:

        (list 5 4 3 a b c)
      

Compondrá y devolverá una lista conteniendo los valores de las variables a, b y c. Por ejemplo:

        (let*  (
                  (a 1)
                  (b 2)
                  (c 3)
               )
               (list 5 4 3 a b c)
        )
      

Este código crea la lista (5 4 3 1 2 3).

Accediendo A Los Valores De Una Lista

Para acceder a los valores de una lista, usa las funciones car y cdr, que devuelven el primer elemento de la lista y el resto de la lista, respectivamente. Estas funciones rompen la lista en la construcción cabeza::cola que mencioné antes.

La Función  car

car devuelve el primer elemento de la lista (la cabeza de la lista). La lista necesita ser no -null. La siguiente devuelve el primer elemento de la lista:

        (car '("first" 2 "third"))
      

que es:

        "first"
      

La Función cdr

cdr devuelve el resto de la lista después del primer elemento (la cola de la lista). Si solo hay un elemento en la lista, devuelve una lista vacia.

        (cdr '("first" 2 "third"))
      

devuelve:

        (2 "third")
      

donde la siguiente :

        (cdr '("one and only"))
      

devuelve:

        ()
      

Accediendo A Otros Elementos En Una Lista

OK, bravo,podemos obtener el primer elemento en una lista, tanto como el resto de la lista, pero ¿como hacemos para acceder al segundo, tercero o otros elementos de la lista?. Existen varias funciones convenientes para acceder, por ejemplo, la cabeza de la cabeza de una cola de una lista (caadr), la cola de la cola de una lista (cddr), etc.

La convención básica para nombrar es fácil. Las a y d representan las cabezas y las colas de la lista, así

        (car (cdr (car x) ) )
      

podría ser escrito como:

        (cadar x)
      

Para ver una lista completa de la lista de funciones, te remitimos al Apéndice, que lista las funciones disponibles para la versión de Scheme usada por Script-Fu.

Para tener práctica con las funciones de acceso a listas, intenta teclear lo siguiente (excepto, todo en una linea si estás usando la consola); usa diferentes variaciones de car y cdr para acceder a los diferentes elementos de la lista:

        (let* (
                 (x  '( (1 2 (3 4 5) 6)  7  8  (9 10) )
                 )
              )
              ; place your car/cdr code here
        )
      

Intenta acceder al número 3 en la lista usando solo dos llamadas a función. Si puedes hacer eso, estás en el camino para llegar a ser un Maestro Script-Fu!.

[Note] Nota

En Scheme, un punto y coma ";" marca un comentario. Esto y todo lo que siga en la misma linea, es ignorado por el interprete de script, así que puedes usar esto para añadir comentarios para refrescar tu memoria cuando vuelvas a mirar tu script.