LISP provee funciones que procesan secuencialmente los términos de
una lista suministrada como argumento.
MAPCAR
(mapcar
función lista1 ... listan
)
- MAPCAR opera sobre los elementos sucesivos de las listas. Primero
se aplica la función al CAR de cada lista, entonces al CADR
de cada una y así sucesivamente. Lo ideal sería que todas
las listas fueran de igual longitud. Si no lo fueran, la iteración
concluye al agotarse la lista más corta y los elementos en exceso de las
demá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 o
se proporcionan mediante variables u otros métodos.
Sobre la función MAPCAR seguramente no encontraremos una
explicación más entusiasta que la de Vladimir Nemerovski a quien
citamos a continuación:
Ahora trataremos de MAPCAR. Esta es una función
que requiere:
- 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)
- alguna lista
- y otras listas opcionales más...
Digamos que la invocamos con (mapcar 'mifunción milista) El
resultado será una LISTA de los RESULTADOS de invocar MIFUNCIÓN
con 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 nuevo
MYSQR aparece aquí precedida de un apóstrofe (QUOTE), ya
que MAPCAR espera que así sea.
MYSQR espera un argumento numérico y eso es lo que obtiene. Si yo la
invocara como (MAPCAR 'MYSQR (list 1 2 "3"))
LISP
intentaría construir una lista de resultados como [1] (list (mysqr
1) (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 cuyo
resultado evalúa como una lista, teniendo también una lista como
primer argumento, de manera que en este punto LISP reconoce tal lista como una
función de usuario, tratando de evaluarla, sustituyendo los argumentos
ficticios 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 ser
utilizada de nuevo, usted puede emplear LAMBDA. Esta función
crea un tipo de FUNCIÓN ANÓNIMA y la devuelve como encerrada en
QUOTE, tal como lo haría DEFUN (sólo que esta
crearía una función vinculada a un NOMBRE que de esta manera
permanecería formando parte del entorno).
MAPCAR es grandiosa en que no necesita saber cual es la longitud
de una lista de datos. No le importa. Simplemente la recorre hasta llegar al
final, con lo que lo sabrá en tiempo de ejecución. De manera que
usted al escribir la función (que en LISP equivaldría al tiempo
de compilación de lenguajes compilados como C, etc.), no necesita saber
la longitud exacta de su lista de datos, lo que ¡ES FENOMENAL! Le permite
tratar fácilmente con información de longitud variable, y no
olvidemos 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 todos
sus 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í. Por
supuesto que yo seré el responsable de suministrar a la función
invocada con el número adecuado de argumentos que le serán
alimentados por MAPCAR, ya que de otra manera obtendré un error
de DEMASIADOS/MUY POCOS ARGUMENTOS cuando LISP eventualmente la
evalú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 de
tipo colección. El argumento función será un
símbolo o una expresión-LAMBDA que será aplicada
a colección.
Ejemplo de utilización de VLAX-MAP-COLLECTION:
Hemos visto anteriormente el desarrolo de una finción que devuelve
una lista con los nombres de las capas contenidas en el dibujo utilizando la
función VLAX-FOR. Una función similar puede
desarrollarse con VLAX-MAP-COLLECTION, con un código resultante
aun más claro y conciso. La función que se pasa a
VLAX-MAP-COLLECTION se definirá en este caso como una
expresión-LAMBDA. Obsérvese que esta expresión
debe 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 anterior
definida con VLAX-FOR.
Unos ejemplos para concluir...
Conversión de cadena a lista:
Conversión de cadena a lista, con MAPCAR, en una sóla
línea. Utilizando esta función podemos convertir al instante
cadenas 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 ejemplo
desarrollado 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 valores
de los vértices de una polilínea. Con los procesos que hemos
estudiado hasta ahora pudiéramos intentar el enunciado de una
función más concisa y clara para obtener este resultado. A ello
dedicaremos el próximo apartado.