3.3. Listas, listas y más listas

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

3.3.1. Definir una lista

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

You've already seen atomic values when we initialized variables in the previous lesson. An atomic value is a single value. So, for example, we can assign the variable x the single value of 8 in the following statement:

(let* ( (x 8) ) x)

(We added the expression x at the end to print out the value assigned to x—normally you won't need to do this. Notice how let* operates just like a function: The value of the last statement is the value returned.)

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)

Intente teclear ambas declaraciones en la consola de Script-Fu y verá como contesta. Cuando teclea la primera declaración, responde con el resultado:

8

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

(1 3 5)

When it replies with the value 8 it is informing you that x contains the atomic value 8. However, when it replies with (1 3 5), it is then informing you that x contains not a single value, but a list of values. Notice that there are no commas in our declaration or assignment of the list, nor in the printed result.

La sintaxis para definir una lista es:

'(a b c)

where a, b, and c are literals. We use the apostrophe (') to indicate that what follows in the parentheses is a list of literal values, rather than a function or expression.

Una lista vacia puede definirse como:

'()

o simplemente:

()

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

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

Note que después del primer apóstrofe, no necesita usar un apóstrofe cuando defina las listas internas. Adelante, copie la declaración en la consola de Script-Fu y mire que devuelve.

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

3.3.2. ¿Como se representan las listas?

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

3.3.3. Crear listas mediante concatenación (Lafunción cons)

One of the more common functions you'll encounter is the cons function. It takes a value and places it to its second argument, a list. From the previous section, I suggested that you think of a list as being composed of an element (the head) and the remainder of the list (the tail). This is exactly how cons functions — it adds an element to the head of a list. Thus, you could create a list as follows:

(cons 1 '(2 3 4) )

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

También, podrías crear una lista con un elemento:

(cons 1 () )

Puede usar, previamente, variables declaradas en lugar de literales, como cabría esperar.

3.3.4. Definir una lista usando la función list

To define a list composed of literals or previously declared variables, use the list function:

(list 5 4 3 a b c)

Esto 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).

3.3.5. Acceder a los valores de una lista

To access the values in a list, use the functions car and cdr, which return the first element of the list and the rest of the list, respectively. These functions break the list down into the head::tail construct I mentioned earlier.

3.3.6. The car Function

car returns the first element of the list (the head of the list). The list needs to be non-null. Thus, the following returns the first element of the list:

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

que es:

"first"

3.3.7. The cdr function

cdr returns the rest of the list after the first element (the tail of the list). If there is only one element in the list, it returns an empty list.

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

devuelve:

(2 "third")

donde la siguiente:

(cdr '("one and only"))

devuelve:

()

3.3.8. Acceder a otros elementos de 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: a y d representan las cabezas y las colas de la lista, así

(car (cdr (car x) ) )

se podría escribir como:

(cadar x)

To get some practice with list-accessing functions, try typing in the following (except all on one line if you're using the console); use different variations of car and cdr to access the different elements of the list:

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

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

[Nota] Nota

In Scheme, a semicolon (;) marks a comment. It, and anything that follows it on the same line, are ignored by the script interpreter, so you can use this to add comments to jog your memory when you look at the script later.