Translate

sábado, 8 de septiembre de 2012

Funciones de mapeo sobre listas

Si se tiene una lista, y se desea realizar operaciones o modificaciones para cada elemento de dicha lista, obteniendo otra de la misma longitud, se puede utilizar una función de mapeo. mapcar es la mas común de tales funciones. mapcar toma una función y uno o más listas, y aplica esa función a cada elemento de la lista, produciendo una nueva lista resultante.

 > (setq una-lista '(1 2 3 4 5))

UNA-LISTA

> (defun doble (n) (* n 2))

DOBLE

> (setq otra-lista (mapcar #'doble una-lista))

(2 4 6 8)

Observe el signo #' antes de la función doble. DOBLE es el nombre del símbolo, (definido previamente con defun), que contiene a la función. La notación #' permite acceder al espacio de función del símbolo DOBLE y pasarla como argumento a mapcar.





- Maestro, ¿¡se pueden pasar funciones como argumentos...!?

- Si, pequeño saltamontes, pues las funciones son tipos de datos en Lisp, sigue practicando...

Otro ejemplo:


> (setq cadenas '("argentina gano tres a uno" "Messi hizo un gol" "Paraguay concreto de penal"))

("argentina gano tres a uno" "Messi hizo un gol" "Paraguay concreto de penal")

> (defun cambia-letra (una-cadena) (substitute  #\@ #\e una-cadena))

CAMBIA-LETRA

> (cambia-letra "cielo celeste")

“ci@lo c@l@st@”

> (setq nuevas (mapcar #'cambia-letra cadenas)


("arg@ntina gano tr@s a uno" "Lio M@ssi hizo un gol d@ tiro libr@" "Paraguay concr@to d@ p@nal")
Para no tener que definir funciones a cada rato, existe la función "sin nombre", lambda que puede pasarse como argumento a mapcar, ahí mismo donde se define.
Para el primer ejemplo de la función doble, sería asi:

> (setq otra-lista (mapcar 

                                      #'(lambda (n) (* n 2)) 
                                      una-lista))
(2 4 6 7)

Para el segundo:

(setq nuevas (mapcar 
                       #'(lambda (una-cadena) (substitute #\@ #\e una-cadena)) 
                       cadenas))

("arg@ntina gano tr@s a uno" "Lio M@ssi hizo un gol d@ tiro libr@" "Paraguay concr@to d@ p@nal") 
Bien, lambda es la función sin nombre. Permite definir de manera instantánea la función que se va a pasar como argumento. Se usa de la siguiente manera:

(lambda (argumento) (cuerpo de la función))

some

Devuelve una valor booleano (T o NIL) si algún elemento de la lista verifica la función aplicada.

> (some #'(lambda (x) (> x 9)) '(1 2 3 4 4 6 78 13))
T

Solo basta que la función que se le pasa como argumento sea booleana, es decir que devuelva T o NIL. Aquí otro ejemplo, no se desespere:

> (some #'(lambda (x) (equal x 'futbol)) '(futbol basquet voley handball golf))
T

every

Esta es como la anterior, pero todos los elementos de la lista deben cumplir con la función que se le pasa de argumento.
> (every #'(lambda (x) (atom x)) '("agua" "gota" "barco" "cielo"))
T

atom pregunta si algo es un atomo o una lista. Si es un atomo tal como pueden ser un número, una cadena e incluso una variable, es decir es un solo elemento, devuelve T, si se trata de una lista devuelve NIL.

> (setf lista ‘(1 3 6 45 2))
> (every #'(lambda (x) (>= x 3)) lista)
NIL

apply

Su nombre mismo lo indica, “apply”ca la función a todos los elementos, solo que esta devuelve un solo valor, el valor acumulado.

> (apply #’+ lista)
57

> (apply #’append ‘((a b c) (1 5 9) (“Armando” “Esteban” “Quito”)))
(A B C 1 5 9 "Armando" "Esteban" "Quito")

remove-if

No modifica la lista actual, pero devuelve una lista como resultado de haber eliminado los elementos que verifican la función que se le pasó como argumento.

> (remove-if #'(lambda (x) (> x 5)) lista)
(1 3 2)

>  (remove-if #'atom '("Laurita" 5 ("Jose" valor) (4.1 19 #c(2 3)) “renegado”))
(("Jose" VALOR) (4.1 19 #C(2 3)))

Saludos. Comenten.  :-D