2.5.3. Mapeado sobre Secuencias


LISP provee funciones que procesan secuencialmente los términos deuna lista suministrada como argumento.

MAPCAR

(mapcar función lista1 ... listan)
MAPCAR opera sobre los elementos sucesivos de las listas. Primerose aplica la función al CAR de cada lista, entonces al CADR de cada una y así sucesivamente. Lo ideal sería que todaslas listas fueran de igual longitud. Si no lo fueran, la iteraciónconcluye al agotarse la lista más corta y los elementos en exceso de lasdemás listas se ignoran. MAPCAR devuelve una lista con los resultados de las sucesivas llamadas a la función. Por ejemplo:
_1$ (mapcar 'cons '(a b c) '(1 2 3))
((A . 1) (B . 2) (C . 3))
Una expresión-LAMBDA puede ser utilizada con MAPCAR. Esto resultaútil cuando algunos de los argumentos de función son constantes ose proporcionan mediante variables u otros métodos.

Sobre la función MAPCAR seguramente no encontraremos unaexplicación más entusiasta que la de Vladimir Nemerovski a quiencitamos a continuación:

Ahora trataremos de MAPCAR. Esta es una funciónque requiere:

  1. un símbolo dentro de QUOTE
    o una EXPRESIÓN-LAMBDA (tabién dentro de un QUOTE )
    o una lista de función de usuario (igualmente dentro del QUOTE)
  2. alguna lista
  3. y otras listas opcionales más...

Digamos que la invocamos con (mapcar 'mifunción milista) Elresultado será una LISTA de los RESULTADOS de invocar MIFUNCIÓNcon cada elemento de MILISTA. Por ejemplo, (defun mysqr(x)(* x x)) (mapcar'mysqr (list 1 2 3 4)) devolvería (1 4 9 16) De nuevoMYSQR aparece aquí precedida de un apóstrofe (QUOTE), yaque MAPCAR espera que así sea.

MYSQR espera un argumento numérico y eso es lo que obtiene. Si yo lainvocara como (MAPCAR 'MYSQR (list 1 2 "3")) LISPintentaría construir una lista de resultados como [1] (list (mysqr1) (mysqr 2) (mysqr "3")) y yo obtendría un error de BAD ARGUMENT TYPE al intentar procesar el "3".Observe de nuevo que en esta expresión [1], MYSQR es de nuevo un QUOTED-SYM de una función de usuario previamente definida cuyoresultado evalúa como una lista, teniendo también una lista comoprimer argumento, de manera que en este punto LISP reconoce tal lista como unafunción de usuario, tratando de evaluarla, sustituyendo los argumentosficticios de su lista de parámetros por los argumentos reales.

De manera que si usted quiere que alguna función sea usada en MAPCAR y no desea que ésta permanezca por ahí sin serutilizada de nuevo, usted puede emplear LAMBDA. Esta funcióncrea un tipo de FUNCIÓN ANÓNIMA y la devuelve como encerrada en QUOTE, tal como lo haría DEFUN (sólo que estacrearía una función vinculada a un NOMBRE que de esta manerapermanecería formando parte del entorno).

MAPCAR es grandiosa en que no necesita saber cual es la longitudde una lista de datos. No le importa. Simplemente la recorre hasta llegar alfinal, con lo que lo sabrá en tiempo de ejecución. De manera queusted al escribir la función (que en LISP equivaldría al tiempode compilación de lenguajes compilados como C, etc.), no necesita saberla longitud exacta de su lista de datos, lo que ¡ES FENOMENAL! Le permitetratar fácilmente con información de longitud variable, y noolvidemos que toda la información real sin duda lo es.

Así que puedo (mapcar 'mysqr '(1 2 3)) o puedo (mapcar'mysqr '(1 2 3 4 5)), según haga falta.

Y hay algo más. Digamos que tengo esta función que SUMA todossus argumentos. Es un '+, que puedo invocar como: (+ 1 2) ó (+ 1 2 3) etc.

Ahora cuando escribo (mapcar '+ '(1 2 3) '(4 5 6)) es lo mismo que(list (+ 1 4)(+ 2 5)(+ 3 6))También puedo escribir (mapcar '+ '(1 2 3)'(4 5 6)'(7 8 9)),que equivale a (list (+ 1 4 7)(+ 2 5 8)(+ 3 6 9)) etc.

De manera que tenemos algo más de flexibilidad aquí. Porsupuesto que yo seré el responsable de suministrar a la funcióninvocada con el número adecuado de argumentos que le seránalimentados por MAPCAR, ya que de otra manera obtendré un errorde DEMASIADOS/MUY POCOS ARGUMENTOS cuando LISP eventualmente laevalúe.

Fuente:
Subject: A short course in LISP, LAMBDA, QUOTE,MAPCAR...
Date: Sat, 02 Nov 1996 08:50:38 -0800
From: Lu<learly@ix.netcom.com>

VLAX-MAP-COLLECTION

Aplica una función a todos los objetos de una colección.
(vlax-map-collection colección función)
El argumento colección representa un Objeto-VLA detipo colección. El argumento función será unsímbolo o una expresión-LAMBDA que será aplicadaa colección.

Ejemplo de utilización de VLAX-MAP-COLLECTION:

Hemos visto anteriormente el desarrolo de una finción que devuelveuna lista con los nombres de las capas contenidas en el dibujo utilizando lafunción VLAX-FOR. Una función similar puededesarrollarse con VLAX-MAP-COLLECTION, con un código resultanteaun más claro y conciso. La función que se pasa aVLAX-MAP-COLLECTION se definirá en este caso como una expresión-LAMBDA. Obsérvese que esta expresióndebe pasarse dentro de un QUOTE.

;;Función ListaCapas utilizando VLAX-MAP-COLLECTION
;;;Devuelve una lista con los nombres de capas ordenados alfabéticamente
(setq *EsteDibujo* (vla-get-ActiveDocument (vlax-get-acad-object)))
;se ejecuta previamente
(defun ListaCapas (/ ListaCapas objeto-VLA)
(vlax-map-collection
(vlax-get *EsteDibujo* "Layers")
'(lambda (objeto)
(setq ListaCapas (cons (vlax-get objeto "Name") ListaCapas))
) ;_ fin de lambda
) ;_ fin de vlax-map-collection
(acad_strlsort ListaCapas)
) ;_ fin de defun

Su utilización devuelve idénticos resultado que la anteriordefinida con VLAX-FOR.

Unos ejemplos para concluir...

Conversión de cadena a lista:

Conversión de cadena a lista, con MAPCAR, en una sólalínea. Utilizando esta función podemos convertir al instantecadenas en listas con sus caracteres aislados:

_$ (defun CadenaLista (cadena)(mapcar 'chr (vl-string->list cadena)))
CADENALISTA
_$ (cadenalista "Madrid")
("M" "a" "d" "r" "i" "d")

REMOVE en una sóla línea:

Gracias a Reini Urban hemos podido conocer este brillante ejemplodesarrollado por Sergei Volkov, implementando la función REMOVE (QUITAR)en una sóla línea:

;;;REMOVE, por Segei Volkov
;;;Recibe una expresión
expr y una lista lst.
;;;Devuelve la lista eliminando de ella todas las ocurrencias de la expresión.
;;;Paso 1: Mediante MAPCAR aplica la función LIST a cada término de la lista
;;; Si recibe '(a b c) obtendrá '((a) (b) (c))
;;;Paso 2: Utiliza la función SUBST para sustituir por NIL cada aparición de
;;; la expresión
expr;;;Paso 3: Aplica mediante APPLY la función APPEND a los miembros de la lista.;;; de esta manera desaparecen los NIL (listas vacías) que sustituyeron;;; a la expresión eliminada(defun remove (expr lst) (apply 'append (subst nil (list expr) (mapcar 'list lst))))

Ejemplo:

_$ (remove 'a '( b c d f a g h j))
(B C D F G H J)
_$
Extracción de los vértices de una Polilínea:

En un capítulo anterior, al estudiar los procesos recursivos,habíamos desarrollado una función destinada a extraer los valoresde los vértices de una polilínea. Con los procesos que hemosestudiado hasta ahora pudiéramos intentar el enunciado de unafunción más concisa y clara para obtener este resultado. A ellodedicaremos el próximo apartado.


Inicio |Índice |Continuar....