Está en la página 1de 51

0.

Introducción
LISP se encuentra entre los más antiguos lenguajes de programación de alto nivel aún en uso
generalizado. Fue desarrollado alrededor de 1958 por John McCarthy. La idea de LISP surgió a
partir de un sistema lógico llamado "lambda calculus'' desarrollado por Alonzo Church. Existen
diversas variantes (o dialectos) de LISP, entre las cuales se encuentran Scheme, T, etc. LISP llegó
a ser fundamental como lenguaje de programación para las investigaciones de Inteligencia
Artificial, y sigue aún hoy siendo uno de los más utilizados en este campo. En la década de los '80
se intentó estandardizar el lenguaje. Como resultado surgió el Common LISP cyas
especificaciones se recogen en Common LISP: The Language, 2nd Edition (CLTL2). Common
LISP es actualmente el dialecto más difundido y la base para el desarrollo de numerosas
implementaciones.

Las razones para ello se encuentran en el hecho de poseer una de las formas de sintaxis menos
restrictivas entre los lenguajes de alto nivel. Esto facilita su aprendizaje, al ser muy corto el número
de estructuras y funciones que el estudiante debe conocer para llegar a dominar las técnicas de
programación en este lenguaje. De hecho, este curso se propone la utilización de un subconjunto
de las muchas funciones disponibles para con ellas examinar las técnicas que hacen de LISP un
lenguaje tan especial.

LISP: PARADIGMA DEL ESTILO DE PROGRAMACIÓN


FUNCIONAL
Una de Las características de LISP es la posibilidad de tratar las propias funciones como datos. En
LISP, funciones e incluso programas enteros pueden ser utilizados directamente como entrada a
otros programas o subrutinas. En esto el prototipo para la concepción del lenguaje ha sido la
estructura de las funciones matemáticas. Todos sabemos cómo resolver una expresión del tipo (8 *
((17 + 3) / 4)). Primero hallaríamos el resultado de 17 + 3, que entonces dividiríamos entre 4, para
el resultado multiplicarlo por 8. Es decir, que iríamos resolviendo los paréntesis más interiores y
pasando los resultados a las operaciones descritas en los paréntesis que los contienen.

(* 8 (/ (+ 3 17) 4)) sería la función LISP equivalente.

*, / y + son nombres de funciones LISP. Los números en (+ 3 17) son los argumentos que se
pasan a la función '+'. Pero en (/ (+ 3 17) 4) a la función '/' se le está pasando un
argumento numérico 4, pero también (+ 3 17), otra función con dos argumentos numéricos. Esta es
la esencia de un lenguaje de programación funcional y por eso decimos que LISP lo es.
"Programación funcional significa, segú Graham (On Lisp, pág. 28), escribir programas que operan
a base de devolver valores en lugar de producir efectos colaterales. Estos efectos colaterales
incluyen cambios destructivos en los objetos y la asignación de variables (con setq, por ejemplo)."
Sigue explicando Graham (pág. 31) que "una función destructiva es una que puede alterar los
argumentos que se le pasan. Sólo unos pocos operadores LISP están pensados para producir
efectos colaterales. En general, los operadores propios del lenguaje están pensados de manera tal
que se invoquen para obtener los valores que devuelven. Nombres como sort (vl-
sort), remove (vl-remove) o substitute (subst) no deben llamarnos a engaño. Si usted quiere
efectos colaterales, utilice setq sobre el valor devuelto. Esta misma regla sugiere" -sigue
explicando Graham- "que algunos efectos colaterales son inevitables. Tener la programación
funcional como ideal no implica que los programas nunca debieran tener efectos colaterales. Sólo
quiere decir que no deben tener más de los necesarios."

Esta característica de la programación funcional no es arbitraria. Citando de nuevo a Graham:


Los programadores LISP no adoptaron el estilo funcional por razones meramente estéticas. Lo
usan porque facilita su trabajo. En el entorno dinámico de LISP, los programas funcionales pueden
ser escritos a una velocidad poco usual, y a la vez, pueden ser inusualmente confiables.
En LISP es comparativamente fácil el depurar los programas. Una gran cantidad de información se
encuentra disponible en tiempo de ejecución, lo que ayuda en el rastreo de los errores. Pero aún
más importante es la facilidad con la que pueden probarse los programas. No es necesario el
compilar el programa para probar su funcionamiento como un todo. Podemos probar las funciones
individualmente, llamándolas desde el nivel superior del evaluador.
Esta comprobación de carácter incremental es tan valiosa que el estilo de programación LISP ha
evolucionado para aprovecharla. Los programas escritos en un estilo funcional pueden ser
comprendidos una función a la vez, y desde el punto de vista del lector, esta es su principal
ventaja. Sin embargo, el estilo funcional se adapta perfectamente a la comprobación incremental:
los programas escritos en este estilo pueden ser también probados una función a la vez. Cuando
una función ni examina ni altera el estado exterior, los errores se harán aparentes de inmediato.
Una función así diseñada sólo puede afectar el mundo exterior a través de los valores que
devuelve. En la medida que estos valores sean los esperados, podemos confiar en el código que
los produjo.
Los programadores LISP experimentados de hecho diseñan sus programas de manera que
puedan ser fácilmente probados:

1. Tratan de aislar los efectos colaterales en unas pocas funciones, de manera que la
mayor parte del programa pueda ser escrito en un estilo puramente funcional.
2. Si una función debe producir efectos colaterales, tratan de que al menos posea
una interfaz funcional.
3. Le dan a cada función un propósito único y bien definido

Cuando acaba de escribirse una función, pueden probarla sobre una selección de casos
representativos, y una vez hecho esto pasar a la próxima función.

En LISP, como en cualquier otro lenguaje, el desarrollo se lleva a cabo en ciclos de escritura y
comprobación. Pero en LISP el ciclo es muy corto: funciones aisladas, e incluso partes de
funciones. Y si comprobamos todo a medida que lo escribimos, sabremos dónde buscar cuando se
produzca un error: en lo último que se escribió.

Graham, On Lisp, pág. 37 y 38.

Lisp mas allá de AutoCAD


Hay implementaciones de LISP para uso en el desarrollo de aplicaciones de todo tipo. El lenguaje
se ha normalizado con el nombre de Common LISP (norma ANSI).
Existen entornos de desarrollo disponibles muchas veces como software gratuito a través de
internet. Para más información se recomienda acceder a los siguientes sitios WEB*:

Compiladores y entornos de desarrollo Common LISP para WINDOWS:

 LispWorks
 Allegro CL
 Corman Common Lisp
 CLISP

Los tres primeros son productos comerciales, pero todos ofrecen versiones gratuitas de evaluación
perfectamente adecuadas para el aprendizaje del lenguaje.
CLISP es totalmente gratis (GPL).
LispWorks es especialmente recomendable por su claro entorno de desarrollo (IDE), la capacidad
de construir fácilmente aplicaciones con una interfaz gráfica de usuario (GUI) y la licencia de
evaluación que permite el utilizar el producto por tanto tiempo como se desee, con sólo unas
limitaciones de menor entidad. Le acompaña una muy completa referencia en formato HTML y
PDF.

Allegro CL posee herramientas para el desarrollo de interfaces gráficas mucho más completas,
pero la licencia de evaluación debe ser renovada cada mes.

Corman LISP sólo brinda la posibilidad de utilizar el IDE como evaluación durante un mes, aunque
el compilador en sí es gratuito y posee una consola LISP también gratuita. Para Corman Common
Lisp el profesor Reini Urban ha implementado la posibilidad de su ejecución desde el entorno
AutoCAD lo que que pudiera señalar un camino de desarrollo interesante para el futuro.

Tutoriales en la Red:

El libro de David Touretzky "Common Lisp: A Gentle Introduction to Symbolic Computation", que
está disponible en formato PDF.
El libro de David Lamkins "Successful Lisp: How to Understand and Use Common Lisp" en formato
html.
La Common LISP HyperSpec, de Kent Pitman, que no es un tutorial, sino la referencia definitiva del
lenguaje. Cortesía de la casa que comercializa LispWorks.
El libro de Guy Steele "Common LISP, the language. 2nd Edition", más conocido
como CLTL2, aunque anterior a la norma ANSI, aún merece ser leído.

Si se trata de comprar un libro, lo recomendable sería comenzar, ya sea con el de Paul


Graham "ANSI Common Lisp"o con el de Stephen Slade "Object-Oriented Common LISP".
Después, el PAIP ("Paradigms of Artificial Intelligence Programming") de Peter Norvig es una
lectura obligada.

En la Web sería necesario visitar el CLiki y la página de ALU (Association of LISP Users) para más
enlaces de interés.

Un caso particular es el del Corman Common Lisp, para el que Reini Urban ha implementado la
posibilidad de su ejecución desde el entorno AutoCAD y que pudiera señalar un camino de
desarrollo interesante para el futuro. También existen utilidades para la transferencia de programas
AutoLISP-XLISP desarrolladas por Tony Tanzillo.

* Fuente: Dr. Edmund Weitz (edi@agharta.de) posting al newsgroup comp.lang.lisp Fecha: 2001-
09-28 03:38:20 PST

PARA MUESTRA...
Como una muestra de la capacidad de síntesis y abstracción a la que podemos acceder con LISP
(y una buena cuota de ingenio) reproducimos este pequeño problema planteado a manera de
acertijo hace unos días por Vladimir Nesterovski en el grupo de
noticias autodesk.autocad.customization, y la solución propuesta otro maestro, Tony Tanzillo:

Hola todos, os propongo algo:


crear una función que para una lista de puntos
devuelva un par de puntos con los valores mínimos
y máximos (una suerte de "caja de abarque"), que
funcione para puntos n-dimensionales y que no
emplee LAMBDA o SETQ.
Debe ser simple también. :)
Por ejemplo, para '( (1 2 2) (2 5 4) (3 1 2) )
devolvería '( (1 1 2) (3 5 4) ).
Pasadlo bien, :-)
--
Vlad

Y la respuesta de Tony Tanzillo:

(defun extents (plist)


(list (apply 'mapcar (cons 'min plist))
(apply 'mapcar (cons 'max plist))))

En dos líneas de código resuelta una función que explicada en términos de programación más
convencionales, recibirá dos matrices de dimensiones variables n x m y devolverá una matriz
conteniendo los máximos y mínimos para cada uno de los términos de las matrices recibidas. La
función EXTENTS recibe como argumento una lista de listas y devuelve otra, sin recurrir en ningún
momento a la creación de variables como almacenaje intermedio. Por otra parte el argumento
original permanece inalterado, es decir que se trata de una función no destructiva.

Esto a manera de muestra de lo que trataremos de exponer de aquí en adelante.

1. Visual LISP
PRIMERA PARTE:
EL ENTORNO DE DESARROLLO VISUAL LISP

Índice del Tema

 1.1. El Entorno de Desarrollo Visual LISP

 1.2. El Editor Visual LISP en Detalle

o Barras de Herramientas

o Menú Contextual

o Teclas Rápidas

 1.3. El Trabajo con Visual LISP y AutoCAD

o Barra de Menús

o La Consola Visual LISP

o Uso de las Barras de Herramientas

LISP fué inicialmente fue desarrollado como un lenguaje interpretado, aunque las modernas
versiones cuentan siempre con un compilador que transforma el código fuente en lenguaje de
máquina optimizado. Esta compilación puede ejecutarse de manera inmediata al cargar en el
entorno de desarrollo el código fuente del programa, lo que facilita el desarrollo al disponer de una
evaluación de manera inmediata. Para acceder a este entorno, en el caso del Visual LISP, se
teclea desde la línea de comando de AutoCAD las instrucciones VLISP ó VLIDE (esta última para
compatibilidad con el Visual LISP de la versión 14). Las instrucciones LISP se introducen para su
evaluación en una ventana especial conocida como la Consola Visual LISP. Si no está a la vista,
se puede abrir esta ventana pulsando el botón de la barra de herramientas.

El cursor que aparece junto al símbolo _$ indica que le sistema está listo para recibir las
expresiones LISP del usuario. La imagen anterior muestra el resultado de evaluar una expresión
usando funciones aritméticas. La evaluación se produce al pulsar <INTRO>. Una vez impreso el
resultado aparece de nuevo el símbolo _$ indicando que el sistema está listo para recibir una
nueva expresión. Este ciclo que se desarrolla en el intérprete se conoce como bucle delectura-
evaluación-impresión (read-eval-print loop). Esto significa que el intérprete lee lo que se ha
tecleado, lo evalúay entonces imprime el resultado antes de quedar listo para la nueva expresión.
Al uso de la consola dedicaremos una sección específica de este curso.

El entorno de desarrollo (IDE) Visual LISP cuenta además con un Editor especializado y una serie
de medios para la depuración de los programas muy superiores a los que estaban disponibles en
el viejo AutoLISP.

No obstante, estas lecciones podrán ser seguidas utilizando cualquier versión de AutoLISP. Se ha
tratado de señalar cuando se está hablando de funciones o modos de operación propios del Visual
LISP que noi están disponibles en el entorno AutoLISP.

Hay otras implementaciones de LISP para uso general disponibles muchas veces como software
gratuito a través de internet. Para más información se recomienda acceder a los siguientes sitios
WEB:

AutoCAD-AutoLISP info+tools Página AutoCAD/AutoLISP de Reini Urban.

The Association of LispUsers Página WEB de la Asociación de Usuarios de LISP.

Common Lisp: Intro, Resources & FAQ Introducción al Common LISP.

Un caso particular es el del Corman CommonLisp, para el que Reini Urban ha implementado la
posibilidad de su ejecución desde el entorno AutoCAD y que pudiera señalar un camino de
desarrollo interesante para el futuro. También existen utilidades para la transferencia de programas
AutoLISP-XLISP desarrolladas por Tony Tanzillo.
1.2. El Entorno de Desarrollo
Visual LISP (VLISP) representa una renovación de LISP para AutoCAD, actualizándolo para incluir
prestaciones que ya son normales en los modernos dialectos de LISP que se ajustan a la
normativa COMMON LISP. Aún sin llegar a ser totalmente compatible con esta normativa, es
significativo el incremento de su potencia como lenguaje de programación.
Es particularmente útil la posibilidad que se incorpora para la interacción con la jerarquía de
objetos de la aplicación mediante la interfaz ActiveX ™ Automation de Microsoft, y la posibilidad de
responder a eventos mediante la implementación de funciones diseñadas como reactores.

Como herramienta de desarrollo se aporta un Entorno de Desarrollo Integrado (IDE) que incluye un
compilador y varias utilidades para la depuración.

El IDE Visual LISP incluye:

 Comprobador de Sintaxis que reconoce secuencias AutoLISP erróneas y el uso incorrecto


de los argumentos en llamadas a las funciones primitivas del lenguaje.
 Compilador de Ficheros que incrementa la velocidad de ejecución y constituye una
plataforma de distribución que brinda seguridad al código fuente.
 Depurador de Fuentes, diseñado específicamente para AutoLISP, que permite la ejecución
paso a paso del código fuente en una ventana mientras se observan simultáneamente los
resultados obtenidos en la pantalla gráfica de AutoCAD.
 Editor de Programación que emplea la codificación por color para LISP y DCL, así como
otras características de apoyo sintáctico.
 Formateo LISP automático que redistribuye las líneas de código y las identa para facilitar la
lectura de los programas.
 Amplias características de Inspección y Vigilancia (Watch) que permiten el acceso en
tiempo real a los valores de las expresiones y las variables, y que pueden ser empleadas
tanto para datos LISP como para objetos gráficos de AutoCAD.
 Ayuda sensible al contexto sobre las funciones AutoLISP y una ventana Apropos para
búsqueda de nombres de símbolos.
 Sistema de Administración de Proyectos que facilitan el mantenimiento de aplicaciones con
múltiples ficheros fuente.
 Empaquetado de los ficheros AutoLISP compilados en un único módulo de programa.
 Capacidad para guardar y recuperar la configuración del Escritorio para reutilizar la
distribución de ventanas de cualquier sesión anterior de VLISP.
 Consola Visual LISP Inteligente que permite un nuevo nivel de interacción del usuario, con
funciones que amplían las de la ventana de texto habitual de AutoCAD.

1.3. El Trabajo con Visual LISP y AutoCAD


VLISP posee su propia ventana de aplicación distinta de la de AutoCAD, pero no puede ejecutarse
de manera independiente. Para acceder al IDE Visiual LISP, antes deberá haberse iniciado una
sesión de AutoCAD.

Iniciar Visual LISP


Como se dijo antes, Debe haberse iniciado una sesión de AutoCAD. Esta sesión puede contener
sólo un dibujo vacío, o pueden estar abiertos dibujos cuyo contenido se desee procesar.

Para activar el IDE VLISP tenemos tres opciones:


 Seleccionar del menú Herramientas>AutoLISP>Editor Visual LISP
 Teclear en la línea de comandos: VLISP
Nota: Hemos encontrado al menos en una versión localizada
española que el comando VLIDE no es reconocido por el sistema.
La Ayuda de esa misma versión aeñala como alternativa el
comando VISUALLISPIDE, que tampoco es reconocido. En estos
casos siempre se puede recurrir al comando VLIDE, descrito en el
punto siguiente.
 La versión anterior de Visual LISP utilizaba con los mismos fines el
comando VLIDE, que sigue siendo reconocido por la versión 2000.
De hecho, internamente la llamada de AutoCAD al IDE Visual LISP
se realiza mediante este comando, que veremos aparecer en la
línea de comandos cada vez que se cambie a ese entorno.

La Ventana de la Aplicación

Al iniciarse Visual LISP pasa a primer plano la siguiente ventana de aplicación:

Barra de Menús
Asumimos que el lector está familiarizado con el uso de menús desplegables en AutoCAD u otras
aplicaciones. Sólo cabría destacar que éstos menús son sensibles al contexto en que se utilizan.
Es decir, que algunas opciones que pueden estar activas si se abre la ventana del Editor pueden
no estarlas si el foco se encuentra en la Consola o en la ventana de TRACE.
Las funciones de la aplicación se distribuyen entre los menús desplegables de la siguiente manera

FILE
Creación de nuevos ficheros de programas abiertos para su edición
Apertura de ficheros existentes
Guardar los cambios efectuados
Compilar aplicaciones Visual LISP
Imprimir los ficheros de programas
EDIT
Copiar y Pegar texto
Deshacer el último cambio en el Editor o la última función ejecutada desde la Consola
Seleccionar texto en el Editor o la Consola
Comprobar el cierre de paréntesis
Recuperar funciones ejecutadas desde la Consola
SEARCH
Buscar y Reemplazar texto
Colocar marcadores de referencia (bookmarks) y navegar en el texto utilizando estos
marcadores.
VIEW
Buscar y mostrar el valor de variables y símbolos en su código AutoLISP.
PROJECT
Trabaja con los proyectos y la compilación de programas
DEBUG
Establecer y quitar puntos de ruptura en los programas
Ejecutar programas paso a paso comprobando el estado de las variables y el valor
devuelto por las expresiones.
TOOLS
Establecer las opciones para el formateado del texto y varias otras opciones del entorno,
tales como la ubicación de ventanas y barras de herramientas.
WINDOW
Organiza, abre y cierra ventanas en el IDE.
HELP
Pues eso, la Ayuda en línea.

Uso de las Barras de Herramientas


Visual LISP dispone de cinco Barras de Herramientas que pueden activarse/desactivarse desde el
menú View>Toolbars... que abre el siguiente diálogo:

Estas cinco Barras de Herramientas contienen las opciones u comandos esenciales del IDE,
facilitando el acceso a los mismos.
Contiene las herramientas usuales de Crear Nuevo, Abrir, Guardar, Imprimir, Cortar,
Copiar, Pegar, Deshacer, Rehacer y por último un acceso a la fución Apropos que sirve
para completar el texto buscando una correlación de una subcadena con nombres de
funciones, etc.

Incluye las funciones de Buscar, Buscar y Reemplazar. Además una casilla de lista
desplegable donde se guardan los términos anteriormente buscados durante la sesión de
trabajo, lo que permite repetir una busqueda con más facilidad, cosa que se hace con la
herramienta situada a la derecha de la casilla. Por último incluye una serie de herramientas
para navegar dentro del texto mediante marcadores, que se introducen con la herramienta
de la izquierda, se avanza o retrocede con las dos siguientes y se eliminan con la última.

La barra Tools (Herramientas) opera sólo con la ventana del Editor activa. Sus funciones
son, de izquierda a derecha: cargar el código del Editor para su ejecución desde la
Consola, cargar sólo el código seleccionado, comprobar la sintaxis de todo el contenido de
la ventana del Editor, o con la siguiente, comprobar sólo lo seleccionado. Para formatear el
texto se utilizan los próximos dos botones, el primero para todo el editor y el segundo sólo
para el textoseleccionado. Los dos siguientes botones sirven para marcar como
coimentario el texto seleccionado o para desmarcarlo. Y por supuesto, el último se trata de
la Ayuda en línea.

Los tres primeros botones de esta barra determinan la acción al encontrar un punto de
ruptura durante la evaluación. El primero entra en las expresiones anidadas posteriores al
punto de ruptura, evaluándolas desde la más interior. El segundo evalúa esta expresión y
se detiene antes de la siguiente para de nuevo decidir si se quiere entrar a evaluar las
expresiones anidadas. El tercer botón continúa hasta el final de la función en curso y
entonces cuando se detiene de nuevo la evaluación.
El segundo trío de botones tene que ver con las acciones a tomar cuando se produce una
ruptura del flujo de ejecución a causa de un error, o de que se alcance un punto de ruptura
prefijado dentro del programa. Aunque es un tema que se explicará más adelante, cabe
decir ahora que estos estados de suspensión en la ejecución del programa se utilizan para
examinar los valores asumidos por las variables, cambiarlos si es preciso, etc.
El primer botón (Continue) permite terminar con esta pausa y continuar la ejecución normal
del programa. El segundo botón (Quit) permite abandonar el nivel de evaluación actual
(pueden superponerse varios ciclos de evaluación si se producen varios errores durante la
depuración) y pasar al nivel de más arriba. Y el tercer botón (Reset) pasa el control de la
ejecución directamente al nivel superior (Top Level).
El tercer grupo de botones incluye otras útiles herramientas de depuración. El botón Toggle
Breakpoint permite añadir un nuevo punto de ruptura en el programa, situado en la
posición actual del cursor. El segundo botón (Add Watch) da acceso al diálogo que permite
seleccionar un nombre de variable para observar sus resultados durante la ejecución.
Estos resultados se exhiben en una ventana especial, la ventana Watch.
El botón Last Break resalta en la ventana del editor la expresión que dio origen a la última
ruptura. En caso de error, de esta manera se detecta de inmediato dónde se produjo éste.
El último botón no es realmente un botón de comando. Sirve simplemente para indicar si la
interrupción actual se encuentra antes o después de la expresión.

El primer botón sirve para poner en primer plano la ventana de aplicación de AutoCAD. El
segundo botón abre un menú donde podemos seleccionar la ventana del IDE Visual LISP
que deseamos poner en primer plano. Esto se hace necesario pues podemos tener
abiertas de manera simultánea un gran número de programas y puede no der fácil localizar
aquélo que queremos.
El tercer botón traslada el foco a la Consola de Visual LISP. El siguiente permite activar la
característica de Inspección (Inspect). Inspect permite examinar y modificar objetos
AutoLISP así como AutoCAD. La herramienta Inspect crea una ventana separada para
cada objeto sometido a inspección.
La siguiente herramienta (Trace Stack) necesita explicaciones que se salen del marco de
esta introducción. Baste decir que nos permite acceder a la memoria de pila donde se
guardan las llamadas a función. Puede invocarse en un momento de suspensión en la
ejecución de un programa y permite mediante un menú contextual acceder a datos
relacionados con la operación del programa.
El botón que le sigue (Symbol Service) está diseñado para simplificar el acceso a las
distintas utilidades de depuración relacionadas con símbolos. Podemos resaltar cualquier
nombre de símbolo en el Editor y al pulsar sobre este botón se abrirá la ventana Symbol
Service donde se muestra el valor vinculado. Este valor se puede cambiar directamente en
esta ventana. Además tiene una barra de herramientas que permiten otros procesos con el
símbolo seleccionado.
El siguiente botón permite abrir la ventana Apropos que describimos en detalle más
adelante
Y por último un botón que permite acceder a la ventana Watch.

La Consola Visual LISP

Aunque parecida a la ventana de texto de AutoCAD en el hecho de que se puden introducir


funciones para evaluarlas y obtener el resultado en pantalla, la Consola es una herramienta de
mucha mayor potencia y existen varias diferencias en su manera de operar que es importante
tener en cuenta.

Por ejemplo, para conocer el valor asociado a un símbolo no es necesario, como en AutoCAD,
precederlo de un signo de admiración <!>. Basta teclear el nombre de la variable y pulsar
<INTRO>. En la Consola se emiten una serie de mensajes de diagnóstico durante la ejecución de
las funciones y si se encuentra un error interrumpe la ejecución y habilita un nuevo nivel de
evaluación donde podemos ensayar cambios en valores de variables y realizar pruebas para
detectar los problemas existentes. De producirse un nuevo error, se habilita un nuevo nivel y así
sucesivamente, hasta que decidamos regresar al nivel superior. Las baras de desplazamiento de la
consola nos permiten revisar los resultados anteriores.

Las prestaciones más importantes de la Consola se resumen a continuación:


 Evaluar expresiones AutoLISP y mostrar el resultado devuelto por dichas expresiones.
 Introducir expresiones AutoLISP en líneas múltiples pulsando para el cambio de líne la
combinación <CTRL> + <INTRO>. Pulsar sólo <INTRO> provocaría la evaluación de la
expresión tecleada hasta entonces.
 Evaluar múltiples expresiones a la misma vez.
 Copiar y transferir texto entre las ventanas de la Consola y el Editor. La mayor parte de los
comandos de texto están disponibles también en la Consola.
 Recuperar expresiones tecleadas anteriormente en la Consola, pulsando la tecla <TAB>.
Pulsando esta tecla varias veces se van recuperando las expresiones anteriores. Para
realizar el ciclo en sentido inverso puede utilizarse la combinación <SHIFT> + <TAB>.
 La tecla <TAB> también permite realizar una búsqueda de carácter asociativo a través del
conjunto de expresiones anteriores. Si se quiere buscar anteriores expresiones de creación
de variables bastaría teclear (SETQ y entonces pulsar <TAB>, con lo que se iría
directamente a la última expresión tecleada que comenzaba así. Para realizar el ciclo en
sentido inverso aquí también puede utilizarse la combinación <SHIFT> + <TAB>.
 Pulsando <ESC> se elimina cualquier texto a continuación del símbolo (prompt) del
evaluador.
 Pulsando <SHIFT> + <ESC> abre una nueva Consola, dejando el texto escrito en la
ventana de Consola anterior sin evaluar.
 Al pulsar el botón derecho del ratón en cualquier punto de la Consola o tecleando <SHIFT>
+ <F10> abre un menú contextual de funciones y opviones VLISP. Esto facilita, por
ejemplo, copiar y pegar texto en la línea de comandos de la consola, buscar texto e iniciar
las utilidades de depuración VLISP.

La Consola Visual LISP en Entorno Multidocumento


(MDI)
AutoCAD 2000 es capaz de abrir varios dibujos a la vez. Esto se conoce como Interfaz
Multidocumento (Multiple Document Interface - MDI) en contraposición con la interfaz de
documento único de versiones anteriores*. Hay una única ventana de Consola para todos los
dibujos AutoCAD abiertos. Cuando se utilizan las barras de desplazamiento para revisar las
expresiones y mensajes de la consola, los veremos todos, aunque se hayan emitido para distintos
dibujos. Esta es otra diferencia en relación con la ventana de texto de AutoCAD, que sólo es capaz
de mostrar los comandosque corresponden al dibujo activo. Dicho de otra manera, cada dibujo
tiene su propia ventana de texto, pero comparten una sóla Consola VLISP. El cambio de contexto
es automático al cambiar de dibujo en AutoCAD. El dibujo activo en AutoCAD es siempre el dibujo
activo en VLISP. El nombre del dibujo activo aparece en la barra de título de la aplicación.

El menú Contextual en la
Consola
El pulsar el botón derecho del ratón sobre
cualquier lugar de la ventana de la Consola
abre un menú contextual donde, según esté o
no seleccionado algún texto, se habilitarán
algunas de las siguientes opciones:
Cut
Borra el texto seleccionado de la Consola y lo transfiere al Portapapeles de Windows**.
Copy
Copia el texto seleccionado al Portapapeles de Windows**.
Paste
Pega el contenido del Portapapeles de Windows en la posición indicada por el cursor**.
Clear Console window
Vacía la Ventana de la Consola.
Find
Busca el texto especificado en la Consola.
Inspect
Abre el diálogo de la utilidad Inspect.
Add Watch
Abre la ventana de la utilidad Watch.
Apropos
Abre la ventana del Apropos.
Symbol Service
Abre el diálogo de la utilidad Symbol Service.
Undo
Deshace la última operación.
Redo
Anula el efecto del último Deshacer (Undo).
AutoCAD Mode
Transfiere toda las entradas a la línea de comandos de AutoCAD para su evaluación.
Toggle Console Log
Copia la salida de la Consola a un archivo de registro (log file).

Cómo utilizar la Consola para seguir este Curso:


La consola es la herramienta fundamental que utilizaremos para seguir este curso. Encontraremos
fragmentos de código como éste (que fue ya citado en la Introducción):

(defun extents (plist)


(list (apply 'mapcar (cons 'min plist))
(apply 'mapcar (cons 'max plist))))

Podemos seleccionar dicho fragmento en nuestro browser utilizando el ratón y copiarlo (<CTRL> +
<V>), para después pegarlo en la consola.
Hecho esto, pulsamos <INTRO> para que se evalúe el contenido de la consola, con lo que ya
estará definida la función EXTENTS. Esta función requiere como argumento una lista de puntos
(entendiéndose por puntos una lista de tres números reales representando las coordenadas X, Y,
Z. Supongamos que queremos utilizar la lista:

'((162.75 35.76 145.99)


(127.77 25.37 91.72)(139.355 1.40 0.088)
(242.12 59.34 121.08)(260.897 64.92 30.33)
(299.29 76.33 -55.96)(187.13 -9.28 235.85)
(313.10 -37.47 96.17))

Para ello la introducirámos en la consola (también podemos copiar y pegar) una nueva expresión
con el nombre de la función y la lista como único argumento:

Y entonces, pulsando <INTRO> obtendremos el resultado devuelto:


Obsérvese cómo los colores identifican los componentes de las expresiones, rojo para los
paréntesis, azul para las funciones, verdeazul para los números reales. Una vez evaluada los
colores del texto cambian a negro, con lo que se identifica fácilmente qué formas son las que está
en condiciones de ser evaluadas.

* AutoCAD 2000 puede configurarse para trabajar en modo de documento único. Para ello se
activa la variable de sistema SDI. El valor por defecto de SDI es 0, cambiándolo a 1 se pasa a
trabajar en modo de documento único. Trabajando en este modo, la ventana de texto de AutoCAD
contendrá los comandos emitidos para los sucesivos dibujos abiertos.

** Es posible realizar operaciones de cortar, copiar y pegar entre la consola de VLISP y la ventana
de texto de AutoCAD.

1.2. El Editor Visual LISP en Detalle


Es más que un simple editor de texto. Será, en realidad, nuestro lugar de trabajo habitual para la
programación LISP dentro de AutoCAD. Cada fichero de programa abierto tendrá su propia
ventana del Editor

Un programa en el editor tendrá más o menos este aspecto:


Codificación sintáctica por color
Lo que primero llama la atención la ventana del editor es el color que adoptan los diferentes
componentes del programa. El editor identifica las distintas partes de un programa LISP y le asigna
distintos colores. Esto permite detectar a primera vista elementos tales como nombres de función,
números enteros o reales y cadenas, distinguiéndolos de los nombres de funciones y variables
asignados por el usuario. Los errores mecanográficos saltan así a la vista de manera inmediata.
Estos colores pueden personalizarse a gusto del usuario.

Controles de la Ventana del Editor


La ventana del Editor no posee Barras de Menús ni de Herramientas. Al estar el foco situado en
una ventana del Editor se activarán las opciones de Menú y las Herramientas de la ventana de la
Aplicación que pueden usarse para operaciones del Editor. Muchas de las opciones pueden
también ser ejecutadas desde el menú contextual que se abre al pusar el botón derecho del ratón.
Existe la posibilidad de utilizar también las combinaciones de teclas rápidas usuales en los editores
de texto y además algunas combinaciones que se utilizan para funciones exclusivas de este editor.
En términos generales, además de la codificación por color el editor ofrece otras ayudas que
facilitan grandemente el desarrollo de programas. Algunas de estas utildades son:

 Comprobación del cierre de paréntesis


 Formateo del Texto
 Comentarios automáticos en los cierres de Expresiones

 Comentado y Descomentado automático de las líneas seleccionadas
 Búsqueda y Sustitución de Texto
 Comprobación de la Sintaxis
 Carga de expresiones LISP para ser probadas.

En los próximos apartados pasaremos a exponer estas funcionalidades:

 Barras de Herramientas
 Menú Contextual
 Teclas Rápidas

Copias de Seguridad

El Editor VLISP viene configurado para hacer siempre


copias de seguridad de los ficheros. Estas copias de
seguridad se sitúan en el mismo directorio de la fuente
del programa usando el mismo nombre y la extensión
_ls. De esta manera la copia de seguridad del
fichero caras.lsp se llamará caras._ls. Para
recuperar la última versión guardada de un fichero se
emplea la opción Revert del menú Files.

Barras de Herramientas
Casi todas las funcionalidades del programa pueden accederse desde iconos de las Barras de
Herramientas. Los iconos que aparecen agrisados cuando se activa la ventana del Editor no son
utilizables en este contexto. Las Herramientas utilizables para operaciones en el Editor son:
Herramientas de Edición

Búsqueda y Marcadores

Revisión y Formateo

Acceso a otras Ventanas de la


Aplicación
Utilidades de Depuración

Herramientas de Edición
Esta barra incluye las herramientas de edición acostumbradas en todo programa Windows,
además de una propia para completar nombres de símbolos:

 Crear nuevo archivo.


 Abrir un archivo existente.
 Guardar el contenido de la ventana del editor.
 Imprimir
 Cortar Texto copiándolo al Portapapeles. *
 Copiar Texto al Portapapeles.*
 Pegar Texto desde el Portapapeles.*
 Deshacer la última operación.
 Rehacer lo deshecho en la operación anterior.
 Completar el nombre de un símbolo.

Completar Nombres de Símbolos


La Barra de Herramientas de Edición incluye una
herramienta para completar nombres de Símbolos. Este
Icono realiza una búsqueda inteligente de nombres de
símbolos definidos en el sistema. Al teclear algunas letras
del nombre, el pulsar este icono inicia la búsqueda. Según
la cantidad de símbolos que pudieran corresponder a los
caracteres tecleados, puede abrir un menú contextual en la
posición del cursor, abrir la ventana de resultados de
Apropos o abrir la ventana de inicio de búsqueda de
Apropos si fuera demasiado extensas las opciones posibles
(por ejemplo, teclear una sóla letra inicial). A esta función
puede accederse desde el Menú Search>Complete Word by
Apropos... y también con la combinación de teclas rápidas
<CTRL> + <SHIFT> + <BARRA ESPACIADORA>
Herramientas de Búsqueda de Texto

Búsqueda de texto en múltiples ficheros

La búsqueda de una expresión puede realizarse tanto en el fichero que se edita


como en los ficheros del proyecto u otros grupos de ficheros seleccionados. Desde
el Menú se accede mediante Search>Find o mediante las teclas rápidas <CTRL> +
<F>.
La característica más intere-
sante de la herramienta de
búsqueda del Editor VLISP
es su capacidad de buscar en
un grupo de ficheros
seleccionados y mejor aún,
en los ficheros que
configuran un proyecto. El
resultado de la búsqueda se
muestra en una ventana de
salida, llamada <Find
Output>, donde aparecen
completas las expresiones
donde se emplea el término
buscado. Se puede configurar
la herramienta de búsqueda
para que inserte
marcadores (bookmarks) cada
vez que encuentre el término
buscado, de manera
automática. Para ello se
deberá marcar la casilla Mark
Instances (Marcar Instancias)
Buscar y Reemplazar
Permite buscar y reemplazar texto en la ventana activa del Editor. Se accede a esta opción
desde el menú Search>Replace... (Teclas <CTRL> + <H>).

Memorización de búsquedas anteriores

Los términos utilizados en búsquedas anteriores se guardan en una lista desplegable para
su reutilización.

Inserción de Marcadores

Los marcadores permiten desplazarse dentro del texto de marcador en marcador.


Disponible en el menú Search>Bookmarks>Toggle Bookmark. Hay problemas con los
marcadores al usar la opción de formateo automático del texto. (ver nota más abajo).

Herramientas de Revisión y Formateo

Carga de Expresiones LISP Seleccionadas


A medida que se escriben, las expresiones seleccionadas pueden cargarse para ser
evaluadas. Al ejecutarse la carga el foco pasa a la ventana de la Consola VLISP.
Disponible en el Menú como Tools>Load Selection (<CTRL> + <SHIFT> + <E>)

Carga de la Ventana del Editor

Puede cargarse también para su


ejecución el contenido total actual
de la ventana del Editor y no sólo
las expresiones seleccionadas. En
ambos casos se informará de los
errores que impidan la carga del
programa, aunque no de los
errores sintácticos que pudieran
existir. Desde el menú
Tools>Load Text in Editor
(<CTRL> + <ALT> + <E>)
Comprobación del Código Seleccionado

Comprueba automáticamente la corrección del código tecleado. Puede comprobar


todo el contenido de la ventana o sólo de las expresiones seleccionadas. Los
resultados de la comprobación pasan a la ventana Build Output. En el ejemplo
siguiente se ha suprimido intencionalmente uno de los argumentos necesarios para
ls función CONS, lo que es detectado al ejecutar la comprobación. Esta opción está
disponible desde el menú Tools>Check Selection o con la combinación de teclas
<CTRL> + <SHIFT> + <C>.

Comprobación de la Sintaxis del Programa

El Editor posee una herramienta para comprobar la sintaxis del código tecleado.
El resultado pasa a una ventana llamada Build Output, donde se señalan no sólo
los errores evidentes sino determinadas situaciones que deben ser manejadas con
cierto cuidado. Aplicada la comprobación de Sintaxis al código anterior
obtendríamos la siguiente advertencia:

Esto no impide la ejecución del programa y corresponde a una técnica de


programación perfectamente válida en LISP, donde una función puede siempre
ser empleada como dato. Esta opción se encuentra también en el menú
Tools>Check Text in Editor (<CTRL> + <SHIFT> + <C>).
Formateo del Texto

El editor tiene opciones para formateo del texto, haciendo identaciones de manera
automática. El estilo de formateo puede ser personalizado en cierta medida. Puede
formatearse todo el contenido de la ventana o sólo las líneas seleccionadas.
Nota: Aunque no lo hemos encontrado descrito en la documentación del programa, cuando
se formatea un texto que contiene marcadores, éstos se trasladan al inicio del bloque
seleccionado para su formateo. De manera que si tenemos varios marcadores establecidos
y formateamos todo el contenido de la ventana del editor, perderemos los marcadores
quedando sólo uno en la primera línea de la ventana del editor, lo que obviamente quita
toda utilidad que pudiera tener esta función de inserción de marcadores.Comentarios
automáticos de cierre de Expresión
Entre las opciones de formateo del texto, además de la identación se incluye la posibilidad
de incluir comentarios al cierre de los paréntesis que indican a que función corresponden
cuando dicha función abarca varias líneas.

Comentado y Descomentado automático de las líneas


seleccionadas

Los comentarios se destacan mediante el esquema de colores elegido con fondo gris, pero
además de ello, la inclusión de los caracteres <;;;> al inicio de la línea se realiza mediante
una opción del menú Edit>Extra Commands>Comment Block y se quitan mediante
Edit>Extra Commands>Uncomment Block.
Si se estuvieran editando archivos DCL, los caracteres introducidos como señal de
comentario serán dos barras inclinadas <//>.

Ayuda

Esta barra de Herramientas incluye también el Icono para el Acceso a la Ayuda en-línea.

Acceso a Otras Ventanas de la Aplicación


Estas Herramientas permiten Acceder a las ventanas de:

 Autocad
 Otras Ventanasde Visual LISP, incluyendo las de otros ficheros abiertos para su edición.
 La Consola Visual LISP
 La ventana de Inspección de objetos LISP y AutoCAD.
 El Trace Stack, que guarda la memoria de pila de errores.
 El Symbol Service para la gestión de Símbolos.
 La Utilidad de Apropos.
 La Utilidad de Watch.
Utilidades de Depuración
Sólo tres de las herramientas se encuentran disponibles cuando está activa la ventana del Editor:

 Insertar Punto de Ruptura.


 Añadir el símbolo seleccionado a la ventana de Watch.
 Resaltar en el editor el código que provocó la última interrupción en la ejecución del
programa.
* Es posible realizar operaciones de cortar, copiar y pegar entre el Editor VLISP y la ventana de
texto de AutoCAD.

Menú Contextual
El pulsar el botón derecho del ratón sobre cualquier lugar de la ventana del
Editor abre un menú contextual donde, según esté o no seleccionado algún
texto, se habilitarán algunas de las siguientes opciones:
Cut
Borra el texto seleccionado de la Consola y lo transfiere al
Portapapeles de Windows*.
Copy
Copia el texto seleccionado al Portapapeles de Windows*.
Paste
Pega el contenido del Portapapeles de Windows en la posición
indicada por el cursor*.
Find
Busca el texto especificado en una o más ventanas del Editor.
Go to Last Edited
Desplaza el cursor hacia la última posición editada.
Toggle Breakpoint
Coloca un punto de ruptura en la posición del cursor, o lo elimina
en caso de que ya existiera uno en dicha posición.
Inspect
Abre el diálogo de la utilidad Inspect.
Add Watch
Abre la ventana de la utilidad Watch.
Apropos
Abre la ventana del Apropos.
Symbol Service
Abre el diálogo de la utilidad Symbol Service.
Undo
Deshace la última operación.
Redo
Anula el efecto del último Deshacer (Undo).
AutoCAD Mode
Transfiere toda las entradas a la línea de comandos de AutoCAD
para su evaluación.
Toggle Console Log
Copia la salida de la Consola a un archivo de registro (log file).

* Es posible realizar operaciones de cortar, copiar y pegar entre el Editor VLISP y la ventana de
texto de AutoCAD.

Teclas Rápidas
Las siguientes combinaciones de teclas rápidas son características específicas de este editor:

Comandos de ARCHIVO:
<CTRL> + <S>
Guarda el contenido de la ventana activa del Editor.
<CTRL> + <ALT> + <S>
Guarda el contenido de la ventana activa del Editor con otro nombre de archivo.
<CTRL> + <SHIFT> + <S>
Guarda el contenido de todas las ventanas de Editor abiertas.
<CTRL> + <F4>
Cierra la ventana de Editor activa.
<CTRL> + <P>
Imprime el contenido de la ventana de Editor activa.

Comandos de Edición:
<CTRL> + <Z>
Deshacer la última operación en el Editor. Soporta ilimitadas operaciones de Deshacer,
hasta la última ocasión en que se guardó el contenido del Editor a disco. Una vez guardado
es imposible deshacer. En ese caso, si fuera necesario, habría que recuperar la copia de
seguridad mediante la opción Files>Revert.
<CTRL> + <V>
Pegar el contenido del Portapapeles en el lugar señalado por el cursor.
<SUPR>
Borrar el Texto señalado o el carácter a la derecha del cursor.
<CTRL> + <A>
Seleccionar todo el contenido de la ventana del Editor.
<CTRL> + <M>
Abre un menú desplegable con las opciones de búsqueda del cierre de paréntesis.
<CTRL> + <)>
Desplaza el cursor hasta el paréntesis de cierre correspondiente.
<CTRL> + <(>
Desplaza el cursor hasta el paréntesis de apertura correspondiente.
<CTRL> + <SHIFT> + <)>
Selecciona la expresión hasta el paréntesis de cierre corresondiente, resaltándola en vídeo
inverso.
<CTRL> + <SHIFT> + <(>
Selecciona la expresión hasta el paréntesis de apertura corresondiente, resaltándola en
vídeo inverso.
<CTRL> + <E>
Abre un menú desplegable con una serie de comandos adicionales:
 Identar Bloque
de Texto.
 Suprimir la
Identación de
un bloque de
Texto.
 Identar hasta
el nivel actual
 Añadir un
prefijo a cada
línea de texto
seleccionada.
 Añadir texto al
final de cada
línea
seleccionada.

 Marcar el
bloque
seleccionado
como
comentario.
 Desmarcar
como
comentario el
bloque
seleccionado.
 Guardar
bloque de
texto
seleccionado a
un archivo.

 Convertir el
texto
seleccionado a
mayúsculas.
 Convertir el
texto
seleccionado a
minúsculas.
 Cambiar a
mayúsculas la
primera letra
de cada
palabra.

 Insertar
Fecha.
 Insertar Hora.
 Definir el
formato de
fecha y hora.

 Ordenar
alfabéticament
e las líneas
seleccionadas.

 Insertar el
contenido de
un archivo de
texto en el
lugar indicado
por el cursor

 Borrar desde
la posición del
cursor hasta el
final de la
línea.
 Borrar
espacios en
torno a la
posición actual
del cursor.

Comandos de Búsqueda:
<CTRL> + <F>
Buscar texto.
<CTRL> + <H>
Buscar y sustituir texto.
<CTRL> + <BARRA ESPACIADORA>
Completar una palabra por similitud a otras existentes en la ventana actual del Editor.
Cuando ya se ha tecleado un nombre anteriormente, El editor VLISP facilita el incorporarlo
de nuevo al documento con sólo teclear los caracteres iniciales. Si en el ejemplo de arriba
quisiéramos teclear de nuevo el nombre de la función PosVert bastaría teclear Po y
después pulsar <CTRL> + <BARRA ESPACIADORA>. Si en lugar de encontrar PosVert
encontrara el nombre de variable pos, bastaría con volver a pulsar <CTRL> + <BARRA
ESPACIADORA> cuantas veces fuera necesaro para llegar al texto deseado.
<CTRL> + <SHIFT> + <BARRA ESPACIADORA>
Completar una palabra mediante APROPOS (buscando en todo el conjunto de símbolos
AutoLISP.
<ALT> + <.>
Poner o quitar marcador.
<CTRL> + <.>
Desplazarse al próximo marcador.
<CTRL> + <,>
Desplazarse al marcador anterior.
<CTRL> + <SHIFT> + <.>
Seleccionar hasta el próximo marcador.
<CTRL> + <SHIFT> + <,>
Seleccionar hasta el marcador anterior.

Comandos de Vistas:
<CTRL> + <SHIFT> + <I>
Abre una ventana de Inspección para introducir una expresión.
<CTRL> + <SHIFT> + <T>
Abre la ventana de Inspección de Trace.
<CTRL> + <SHIFT> + <R>
Abre la ventana de Inspección para la última pila de error.
<CTRL> + <SHIFT> + <S>
Abre una ventana de Inspección para un símbolo.
<CTRL> + <SHIFT> + <W>
Abre la ventana de Vigilancia (WATCH).
<CTRL> + <SHIFT> + <A>
Abre la ventana APROPOS para ayuda con expresiones LISP.
<CTRL> + <SHIFT> + <B>
Muestra los puntos de interrupción actuales (en todos los programas abiertos, no sólo la
ventana activa).
<F6>
Abre la Consola Visual LISP y/o la pone en primer plano.

Comandos del Proyecto:


<CTRL> + <SHIFT> + <P>
Abre un proyecto existente.

Comandos de Depuración:
<CTRL> + <W>
Añadir una expresión a la ventana de Vigilancia (WATCH).
<F9>
Añade o suprime un punto de interrupción en la posición actual del cursor.
<CTRL> + <SHIFT> + <F9>
Suprime todos los puntos de interrupción.
<CTRL> + <F9>
Busca y resalta el código que dio origen a la última interrupción.

Herramientas de Desarrollo:
<CTRL> + <SHIFT> + <E>
Carga y evalúa el código seleccionado.
<CTRL> + <ALT> + <E>
Carga y evalúa el código contenido en la ventana activa del Editor.
<CTRL> + <SHIFT> + <C>
Comprueba la sintaxis de las expresiones seleccionadas.
<CTRL> + <ALT> + <C>
Comprueba la sintaxis del código contenido en la ventana activa del Editor.
<CTRL> + <SHIFT> + <F>
Formatea las expresiones seleccionadas.
<CTRL> + <ALT> + <F>
Formatea el código contenido en la ventana activa del Editor.

Controles de Ventanas:
<ALT> + <F6>
Ajusta la ventana activa al espacio disponible en pantalla.
Comprobación del cierre de paréntesis
Las combinaciones de teclas <CTRL> + <(> y <CTRL> + <)> permiten localizar el
paréntesis de apertura o el paréntesis de cierre respectivamente que corresponda a partir
de la posición donde se sitúa el cursor. Si se pulsa simultáneamente <SHIFT> el texto
quedará seleccionado (en vídeo inverso).
Completar Texto
Cuando ya se ha tecleado un nombre anteriormente, El editor VLISP facilita el incorporarlo
de nuevo al documento con sólo teclear los caracteres iniciales. Si en el ejemplo de arriba
quisiéramos teclear de nuevo el nombre de la función PosVert bastaría teclear Po y
después pulsar <CTRL> + <BARRA ESPACIADORA>. Si en lugar de encontrar PosVert
encontrara el nombre de variable pos, bastaría con volver a pulsar <CTRL> + <BARRA
ESPACIADORA> cuantas veces fuera necesaro para llegar al texto deseado.

2. Técnicas Fundamentales
SEGUNDA PARTE:
TÉCNICAS FUNDAMENTALES DE LA PROGRAMACIÓN
LISP

2.1. Tipos de Datos


Antes de iniciarnos en la programación LISP, examinaremos los datos con que este lenguaje
opera. Las posibilidades de un lenguaje de programación están directamente relacionadas con la
oferta de procedimientos y funciones y en sobre qué tipos de datos pueden ellos operar.

Los tipos de datos originales son los ÁTOMOS y las LISTAS. Los ÁTOMOS y las LISTAS son
mutuamente excluyentes: un objeto LISP es lo uno o lo otro. Con una excepción: la lista vacía o
NIL, que estudiaremos más adelante. Las listas se construyen recursivamente a partir de átomos
y/o listas.

Ejemplos:

ÁTOMOS LISTAS
a ()
juan (juan)
45 (a juan 45 z5mn)
z5mn ((juan 45) a ((z5mn)))

AutoLISP y Visual LISP utilizan además otros tipos de datos que estudiaremos más adelante y que
resultan necesarios para la gestión de los dibujos en el entorno AutoCAD.

Tanto los átomos como las listas son expresiones válidas LISP que el intérprete lee y evalúa. Las
reglas para la evaluación de ambos tipos de objetos se describen a continuación:
ÁTOMOS
Los átomos son las expresiones LISP más elementales. Siempre tienen un nombre
constituido por una secuencia de caracteres y por ello se asemejan a las palabras de un
lenguaje. Los nombres de átomos se separan de otras expresiones mediante espacios en
blanco, paréntesis o cambios de línea. Un átomo no es divisible. Como norma general,
todos los elementos que no sean una lista se consideran átomos. Al recibir un átomo, el
evaluador lisp intenta determinar su valor. Este valor puede estar representado por el
nombre mismo del átomo, que entonces consideraremos como una "constante" o puede
ser un objeto LISP distinto, en cuyo caso estaremos ante un átomo "simbólico". Los
átomos simbólicos se utilizan dentro de los programas para almacenar valores, siendo
conocidos entonces como "variables".

LISTAS

El nombre LISP viene de LISt Processing (Procesamiento de Listas), indicando el


mecanismo fundamental sobre el que se desarrolla el lenguaje. Las listas LISP son grupos
de valores relacionados, separados por espacios e incluidos entre paréntesis redondos "("
y ")". En LISP, el orden de los elementos incluidos en una lista es significativo. En esto se
distingue el concepto de lista del concepto de conjunto, en el que el ordenamiento de los
términos no tiene relevancia. Otra diferencia entre listas y conjuntos reside en que en una
lista pueden haber términos repetidos, mientras que en un conjunto cada término ocurre
una sóla vez. Las listas proporcionan un método eficaz para almacenar valores
relacionados. AutoCAD expresa los puntos 3D como una lista de tres números reales
donde el primer valor es el de la coordenada X, el segundo la coordenada Y, el tercero la
coordenada Z. Esto indica que el orden de los términos de una lista es significativo y en
esto se diferencia del concepto de conjunto. Además una lista admite términos repetidos.
Dentro de las posibles listas podemos distinguir tres casos:

 Listas de un nivel
 Listas anidadas
 La lista vacía

TIPOS DE DATOS ESPECÍFICOS DE AUTOCAD:


 CONJUNTOS DE SELECCIÓN
Los conjuntos de selección son grupos compuestos por uno o varios objetos (entidades).
Las rutinas de AutoLISP permiten añadir o suprimir de forma interactiva objetos de los
conjuntos de selección.

 NOMBRES DE ENTIDAD
Un nombre de entidad es un identificador numérico asignado a los objetos de un dibujo. En
realidad, se trata de un puntero a un archivo mantenido por AutoCAD, en el que AutoLISP
puede encontrar el registro de la base de datos de objetos. Este puntero suele cambiar de
una sesión de trabajo a otra.
 DESCRIPTORES DE ARCHIVO
Los descriptores de archivo son identificadores alfanuméricos asignados a archivos
abiertos por Visual LISP. Cuando sea necesario que una función de Visual LISP lea o
escriba en un archivo, debe hacerse referencia a su identificador.

 SUBRUTINAS, SUBRUTINAS EXTERNAS Y FUNCIONES DE


USUARIO
Funciones Nativas LISP o funciones externas cargadas desde archivos compilados FAS ó
VLX y archivos fuente LISP.

 TABLAS DE PAGINACIÓN
 OBJETOS Y TIPOS DE DATOS ACTIVEX
Objetos propios y determinados formatos para los datos que se pasan a los métodos
ActiveX.

COMPROBACIÓN DEL TIPO DE DATO:


 FUNCIÓN TYPE
Devuelve el tipo de un elemento designado
(type elemento)

2.1.1. Átomos
ÁTOMOS SIMBÓLICOS (S-ATOMS):
Un átomo simbólico es un átomo que representa algo más, como el nombre de una función o el
valor de una variable. Un átomo simbólico si no tiene asignado un valor, al evaluarse devolverá una
lista vacía. Las funciones como set, setq y defun permiten asignarle valores a los Átomos-S.
Los nombres de símbolos no distinguen entre mayúsculas y minúsculas, y pueden ser cualquier
secuencia de caracteres de notación y alfanuméricos a excepción de los siguientes: ( ) . ' " ; .
Un nombre de símbolo no puede estar compuesto sólo por caracteres numéricos ya que un
número se representa a sí mismo y es por tanto una constante. Lo mismo sucede con los nombres
entrecomillados.
 VARIABLES:
Cuando un símbolo se utiliza para almacenar temporalmente datos necesarios para la
ejecución del programa suele identificarse como una ‘variable’. La función (atoms-
family 0) nos devuelve todos los átomos-S evaluados como no-nil en un momento
determinado.

 VARIABLES GLOBALES Y LOCALES:


La función SETQ es el medio fundamental para asociar los símbolos a valores:
(SETQ <símbolo> <valor>)
Esto es equivalente a:
(SET (QUOTE <símbolo>) <valor>)
Es decir, que toma el nombre de símbolo sin evaluar, y le asigna el valor deseado. En este
sentido se dice que SETQ es una "Forma Especial". Una variable creada con SETQ es una
variable global. Esto quiere decir que retiene su valor fuera del programa que la utiliza. Una
variable de este tipo afectaría a cualquier otro programa que utilizara el mismo símbolo.
Las variables locales son aquellas que retienen su valor sólo mientras la función que las
define está activa. Las variables locales se eliminan tan pronto termina la operación de la
función donde se definieron, se desechan automáticamente y el sistema recupera el
espacio de memoria que las variables ocupaban. Esto se conoce como "recolección de
desechos" (garbage collection) automática. Las variables locales resultan por ello más
eficientes en el uso de la memoria. Visual LISP no tiene una función especial para la
creación de variables locales. Las mismas deben declararse expresamente en la lista de
parámetros de la función DEFUN.
Para más información consultar a R. Urban, Using Local Variables?

CONSTANTES:
Los números y las cadenas son formas auto-evaluativas. Estos datos se distinguen de los
átomos simbólicos en que no pueden representar otra cosa que el su propio valor, es decir
que se representan a sí mismos. Entre los valores constantes tenemos los números y las
cadenas.

 NÚMEROS
Los valores numéricos que emplea Visual LISP pueden ser enteros o reales.

 CADENAS DE TEXTO
Una cadena se representa mediante una sucesión de caracteres (letras, números y signos
de puntuación) encerrados entre comillas dobles. Estas comillas dobles de apertura y
cierre no forman parte de la cadena de caracteres en sí misma, sino que constituyen la
manera de indicar al evaluador LISP que se trata de este tipo de dato. Si se quiere tener
comillas dobles como parte de la cadena, deberá precederse el carácter comillas por una
contrabarra: "Esto es una \"Palabra\" entrecomillada". La contrabarra es un
carácter de control que permite incluir cambios de línea, tabuladores, y otros caracteres
especiales en una cadena. Para incluir una contrabarra como parte de la cadena deben
escribirse dos contrabarras, la primera como carácter de control y la segunda para graficar
la contrabarra: "Cadena incluyendo \\". Las cadenas individuales tienen una
limitación de 132 caracteres. En versiones anteriores de AutoCAD, los nombres de tablas
de símbolos se convertían automáticamente a mayúsculas. En AutoCAD 2000 se conserva
el tipo de carácter utilizado, sean mayúsculas o minúsculas. Al hacer comprobaciones de
igualdad de cadenas puede ser necesario por ello realizar conversiones a un mismo tipo de
letra utilizando la función STRCASE.

2.1.1.1. Números Enteros y Reales


ENTEROS
Son números sin separador decimal. Los enteros de AutoLISP son números de 32 bits con signo
cuyos valores están comprendidos entre +2.147.483.648 y -2.147.483.647. Aunque
AutoLISP utiliza internamente valores de 32 bits, los que se transmiten de AutoLISP a AutoCAD y
viceversa están limitados a 16 bits. Por tanto, no pueden transmitirse a AutoCAD valores
superiores a +32767 ni inferiores a -32768.

Sin embargo, VLISP acepta valores fixnum entre los valores límite de:

 MAX-SHORTINT = 32767
 MOST-POSITIVE-FIXNUM = 2147483647
 MOST-NEGATIVE-FIXNUM = -2147483647

Un número mayor o menor se convierte automáticamente en real.


REALES
Contienen un separador decimal. Los comprendidos entre -1 y 1 deben empezar por cero. Los
números reales se almacenan en formato de coma flotante de doble precisión, lo cual proporciona
una precisión mínima de 14 dígitos significativos, aunque el área de comandos de AutoCAD
muestra sólo 6.

Los valores límites son:


MOST-POSITIVE-DOUBLE-FLOAT = 1.797693134862315e+308
MOST-NEGATIVE-DOUBLE-FLOAT= -1.797693134862315e+308
Un número mayor, devuelve infinito:

_$ 1.797693134862316e+308
1.#INF
_$ (setq val 1.797693134862316e+308)
1.#INF
_$ (type val)
REAL
_$ (setq *INFINITO* 2.797693134862316e+308)
1.#INF
_$ (eq *INFINITO* val)
T
_$ (/ 125678 *INFINITO*)
0.0

Se puede establecer una variable global *INFINITO* con: (setq *INFINITO*


1.797693134862316e+308) y utilizarlo como tal en operaciones trigonométricas.
Pueden expresarse en notación científica, que consta de una e o E opcional seguida por el
exponente del número (por ejemplo, 0.0000041 es lo mismo que 4.1e-6). El símbolo pi se
evalúa como la constante real 3,1415...

FUNCIONES DE CONVERSIÓN ENTRE


ENTEROS Y REALES:
(fix número)

Devuelve la conversión de un número real en el próximo entero menor.

(float número)

Devuelve la conversión de un número entero en un número real.

CONSIDERACIONES SOBRE LA CONVERSIÓN ENTRE


NÚMEROS REALES Y ENTEROS
La función fix en realidad lo que ejecuta es un truncamiento del número real hacia cero. Es decir,
devuelve el número entero más próximo a cero. Así (fix 4.7) devolverá 4, es decir, el número
entero menor más cercano al suministrado como argumento. Pero (fix -4.7) devolverá -4, que
es el entero mayor más cercano. En las definiciones de Common LISP, fix equivaldría a la
función truncate.

Steele menciona en CLTL2 otras posibilidades de conversión entre reales y enteros:

floor

convierte su argumento mediante un truncamiento hacia infinito negativo; es decir, que el


resultado es el entero mayor que no es mayor que el argumento.

ceiling

convierte su argumento mediante un truncamiento hacia infinito positivo; es decir, que el


resultado es el entero menor que no es menor que el argumento.

truncate

convierte su argumento mediante un trucamiento hacia cero; es decir, que el resultado es


el entero del mismo signo que el argumento y que posee la mayor magnitud entera que no
es mayor que el argumento.

round

convierte su argumento mediante el redondeo al entero más cercano; si el número se


encuentra exactamente a mitad de camino entre dos enteros (es decir, en la forma entero
+ 0.5), entonces se redondea al entero par más próximo (divisible por 2).

Más adelante desarrollaremos funciones para implementar algunos de estos conceptos que no
aparecen como primitivas de Visual LISP.*

*Ver el capítulo REALES A ENTEROS: TRUCAMIENTO O REDONDEO.

2.1.2. Listas
Por la importancia dentro de LISP del tipo de datos LISTA, citamos in extenso el apartado 2.4 de
CLTL2,

Un CONS es una estructura de información que contiene dos componentes llamados el CAR y el
CDR. La utilización fundamental de los CONSES es como representación de LISTAS.

Una LISTA se define recursivamente ya sea como la lista vacía o como un CONS cuyo
componente CDR es una lista. Una lista es, por consiguiente, una cadena de CONSES enlazados
por sus componentes CDR y terminada por un NIL, la lista vacía. Los componentes CAR de los
conses son conocidos como los elementos de la lista. Para cada elemento de la lista hay un
CONS. La lista vacía no tiene ningún elemento.

Para comprender mejor lo anterior, adelantaremos la mención de la función básica de construcción


de listas, que es la función CONS (que se explica en el apartado FUNCIONES DE
CONSTRUCCIÓN DE LISTAS). Expresado en términos de esta función, la anterior definición de
una lista como una cadena de CONSES sería:
Una LISTA se expresa mediante la escritura de los elementos de la lista ordenados, separados por
espacios en blanco (caracteres de espacio, tabulador o retorno) y rodeados por paréntesis. Por
ejemplo:

(a b c) ;Una lista de tres símbolos


(2.0 (a 1) "*") ;Una lista de tres cosas diferentes: un número real
;otra lista y un carácter asterisco
Nota: El código del ejemplo anterior ha sido modificado para adaptarlo a las convenciones de
AutoLISP/Visual LISP

La lista vacía puede por lo tanto ser expresada como (), ya que se trata de una lista sin elementos.

Una lista punteada (dotted list) es una cuyo último cons no tiene NIL como su CDR, sino otro objeto
de información (que tampoco será un CONS, ya que entonces el CONS anteriormente mencionado
no hubiera sido el último CONS de la lista).

Tal tipo de lista se conoce como "punteada" debido a la notación especial que se emplea en ella:
los elementos de la lista se escriben, al igual que antes, entre paréntesis, pero ... antes del
paréntesis derecho se escriben un punto (rodeado por espacios en blanco) y entonces el CDR del
último CONS. Como caso especial, un CONS aislado se expresa escribiendo el CAR y el CDR
entre paréntesis y separados por un punto rodeado de espacios (par punteado). Por ejemplo:

(a . 4) ;Un cons cuyo car es el símbolo a


;y cuyo cdr es un entero
(a b c . d) ;Una lista punteada con tres elementos cuyo cons final
;tiene el símbolo d en su cdr

Con frecuencia se utiliza el término lista para hacer referencia tanto a verdaderas listas como a
listas punteadas. Cuando resulta importante la distinción, se utilizará el término "verdadera lista"
para referirnos a una lista terminada por NIL. La mayoría de las funciones que se dice operan
sobre listas esperan recibir verdaderas listas como argumento.

Por ejemplo, si en el ejemplo de concatenación de CONSES anterior el elemento de la derecha del


último CONS no hubiera sido NIL (lo que hubiera incluido un par punteado en la lista), el pasar esta
lista como argumento a una función de tratamiento de listas hubiera producido en determinados
casos un error:

A veces se utiliza el término árbol para referirse a algunos CONS y todos los demás CONSES
accesibles a él de manera transitiva a través de enlaces de CAR y CDR hasta alcanzar objetos
NO-CONS; éstos NO-CONSES son conocidos como las hojas del árbol.

Representación de LISTAS como árboles.


Tomado de: Cortés y Sierra, LISP. Editorial Marcombo, Barcelona. 1987.

Las listas, las listas punteadas y los árboles no son tipos de datos mutuamente excluyentes; no son
más que puntos de vista útiles en torno a las estructuras de CONSES. Hay aún otros términos tales
como LISTA DE ASOCIACIÓN. Ninguno de éstos son verdaderos tipos de datos LISP.
Los CONSES constituyen un tipo de dato, y NIL es el único objeto de tipo NULL. El tipo de dato
LISTA significa en LISP la unión de los tipos de datos CONS y NULL, y por ello engloba tanto las
listas verdaderas como las listas punteadas.

FORMATOS DE LISTAS:
Además de lo apuntado más arriba, es conveniente distinguir entre los siguientes tres formatos de
listas:

 LISTAS DE UN NIVEL

Contienen sólo átomos.

 LISTAS ANIDADAS
Contienen a su vez otras listas que se dicen ‘anidadas’. Estas listas anidadas suelen ser
conocidas como sub-listas. El número de niveles de anidación no está restringido ni en su
profundidad ni en su complejidad. El nivel más externo lo llamamos nivel superior o primer
nivel. A los elementos que conforman este nivel los llamamos elementos de primer nivel.

 LISTAS DE ASOCIACIÓN (A-LIST)

Son listas anidadas que se utilizan con frecuencia como estructura de datos en LISP. Una
A-LIST es una lista de pares (CONSES) en que cada par constituye una asociación. El
CAR de uno de estos pares se conoce como la CLAVE y el CDR constituye el DATO. Una
ventaja de la representación como A-LIST es la posibilidad de incrementarla añadiéndole
nuevas entradas al principio de la lista. Más aún, como la función de búsqueda ASSOC
recorre la A-LIST de manera ordenada, las nuevas entradas pueden "enmascarar" las más
antiguas de manera que la información puede ser modificada de forma no destructiva.

 LA LISTA VACÍA (NIL)

Como se dijo antes, es la que no contiene ningún elemento. Se indica como () y recibe un
nombre particular, el de NIL.
La lista vacía tiene un status peculiar en LISP. Es a la vez un átomo y una lista. Como
símbolo representa el valor lógico de FALSO:

_$ ()
nil
_$ (atom nil)
T
_$ (listp nil)
T

 CIERTO Y FALSO

Su negación (not nil) sería el símbolo T que representa la condición lógica de CIERTO.
El símbolo T es también una constante en el sentido de que sólo se representa a sí
mismo.
En Visual LISP, nil y T así como otros elementos que incluyen los operadores aritméticos
(+, -. etc.) son símbolos protegidos. Cualquier intento de asignarle otro valor producirá un
mensaje de advertencia:

Este mensaje aparece como la opción por defecto y pide si se desea entrar en un bucle de
interrupción (break loop). Si se escoge No, el valor del símbolo es modificado. Si se
selecciona Sí, se interrumpe el procesamiento y se entra en un ciclo de interrupción de
Visual LISP, lo que se conoce por el aspecto del símbolo del evaluador, por ejemplo: _1_$.

El control se ha trasladado a la consola de Visual LISP. Para asignar valor al símbolo y


continuar el procesamiento se deberá pular el botón Continuar en la barra de
herramientas de Visual LISP. Para abortar el procesamiento se pulsará Reset .

2.1.3. Función Type


(type dato)

La función TYPE permite examinar el tipo a que corresponde un dato determinado. Los datos que
evalúan como NIL (por ejemplo átomos simbólicos no vinculados a un valor) devuelven nil.

El valor devuelto para cada tipo de dato será alguno de los átomos que se describen a
continuación:

Tipos LISP:

INT
Números Enteros

REAL

Números de Coma Decimal Flotante

LIST

Listas

STR

Cadenas

SYM

Símbolos

Tipos AutoCAD:

ENAME

Nombres de entidades

FILE

Descriptores de archivo

PAGETB

Tablas de Paginación de Funciones

PICKSET

Conjuntos de selección

SUBR

Funciones AutoLISP internas o funciones cargadas desde archivos (FAS o VLX)


compilados.

USUBR

Funciones de usuario cargadas desde ficheros fuente LSP.

EXRXSUBR

Aplicaciones ObjectARX Externas.

Tipos ActiveX:
SAFEARRAY

Matriz del tipo Safearray. Las matrices que se pasan a los métodos ActiveX deben ser del
tipo safearray. Estas matrices son seguras (safe) porque no es posible el asignar de
manera accidental valores fuera de los límites de la matriz provocando una excepción de
datos.

VARIANT

Datos del tipo Variant. Los Variant son en esencia estructuras que se auto-definen y que
pueden contener diferentes tipos de datos. Por ejemplo, cadenas, enteros y matrices
pueden ser representados por Variants. Junto a los datos se guarda la información que
identifica el tipo de dato. Esta característica de auto-definición hace de los Variant útiles
medios para pasar parámetros a los servidores ActiveX.

VLA-object

Objetos ActiveX

2.2. Funciones
Una vez conocidos los tipos de datos pasaremos a estudiar cómo utilizarlos. LISP es un lenguaje
de programación funcional, es decir que suministra funciones para la manipulación de los datos.

Los programas LISP se estructuran como formas y funciones. Según Cortés y Sierra*,

una FORMA es "una expresión simbólica en posición de ser evaluada. El cómputo de valores, en
LISP, se realiza simplemente mediante la evaluación de una FORMA. Todas las FORMAS tienen
valor, sean estas constantes numéricas, átomos literales o expresiones simbólicas. Uno de los
errores más típicos al programar en LISP es el de tratar de evaluar una FORMA que no tiene valor.
El valor de una FORMA es el resultado de evaluarla...
Hay que remarcar que los términos expresión simbólica y FORMA pueden aplicarse a la misma
entidad; su aplicación dependerá del contexto. Una LISTA puede considerarse como un dato,
como una expresión simbólica o considerarse como parte de un procedimiento; la misma LISTA
puede ser considerada como una FORMA" .

Las formas se evalúan (en relación con determinado contexto) para producir valores y efectos
colaterales. Las funciones se invocan aplicándolas a argumentos. (Guy L. Steele Jr., Common Lisp
the Language, capítulo 5). En el entorno Visual LISP se identifican como FORMAS las funciones
de usuario definidas dentro de un fichero fuente LSP. Al cargar un programa se recibe la
confirmación de la carga exitosa del mismo mediante el siguiente mensaje:

Las funciones son conocidas en matemáticas. Mediante ellas se describe algún tipo de relación
entre un grupo de valores. La adición y la multiplicación son funciones simples. Una función más
compleja sería: f(x)=3x2+2x-15
Esta última función también describe una regla de cálculo o algoritmo. Las funciones realizan los
cálculos (en términos LISP, evaluación) utilizando para ello sus argumentos y devuelven un
resultado. A iguales argumentos corresponderán iguales resultados.
Según Cortés y Sierra**:

En LISP, los programas se construyen a partir de la composición de funciones. Esto permite que
tales programas expresen sus propósitos más claramente que los programas convencioneles, y
que resulten más fáciles de entender y de mantener, además de ser más fáciles de construir.

AutoCAD identifica sus funciones LISP primitivas como el tipo de dato SUBR, mientras que
las formas definidas a partir de ellas pertenecen al tipo de dato USUBR o "sub-rutina de usuario"
La función typedevuelve los tipos correspondientes. La llamada a una función toma la forma de
una lista cuyo primer elemento es un átomo simbólico que representa a la función llamada. El resto
de los elementos de esa lista pueden ser átomos y otras listas. Estas sublistas se consideran
también llamadas a funciones y se evalúan para que su valor resultante pueda ser pasado como
argumento a la función que las contiene.

FUNCIONES PRIMITIVAS
Describimos una serie de funciones como ‘primitivas’ en el sentido de que están definidas en la
norma del lenguaje, para distinguirlas de las funciones creadas por el usuario a partir de aquéllas.
En LISP se llama a una función mediante la siguiente sintaxis:
(NOMBREFUNCION <Argumento_1> ... <Argumento_n>)
La suma de dos números sería (+ 5 1)
Para evaluarla LISP procede de la siguiente manera:
a. Lee la expresión completa (+ 5 1)
b. La interpreta como una llamada a una función y la identifica como SUMAR <+>
c. Interpreta 5 como primer argumento y 1 como segundo. El paréntesis de cierre le indica que no
hay más argumentos.
d. La función <+> se evalúa para 5 y 1, devolviendo 6 como resultado, que a falta de otro destino
es impreso en pantalla.
Programar LISP significa llamar a funciones. Básicamente esto se hace usando el tipo de dato
LISTA. Cualquier lista que no tenga otra interpretación como forma especial se considerará una
llamada a una función, donde el primer término se tomará como el nombre de la función y el resto
como sus argumentos. Las listas de llamadas a función pueden estar anidadas, es decir, que una
llamada a función se puede estar utilizando como argumento en otra lista que corresponda a una
llamada a otra función. El resultado de la evaluación de cada nivel de anidación es devuelto al nivel
de superior, hasta llegar al nivel más alto, cuyo valor devuelto se imprimiría en la pantalla de texto
o la línea de comandos.

ARGUMENTOS FUNCIONALES
De lo expuesto más arriba se concluye que en LISP una función es además un objeto de datos que
puede ser suministrado a otra función como argumento. Esta posibilidad contribuye a la facilidad
con que LISP se puede adaptar a las necesidades de cualquier programa mediante la
incorporación de nuevas funciones que en su comportamiento resultan idénticas a las primitivas.

Un programa que admite funciones como datos debe también suministrar alguna manera de
invocarlas. Esto se logra en Visual LISP mediante la función APPLY.

APPLY
(apply función lista-args)

APPLY, como su nombre en inglés indica, aplica una función (que recibe como primer argumento) a
una lista de argumentos. La función puede ser un objeto de código compilado, una expresión-
lambda, o un símbolo. En este último caso se utiliza el valor funcional global de dicho símbolo,
aunque éste no puede ser una forma especial.

_$ (apply '+ '(2 4 6))


12
_$ (apply '(lambda (x y z)(+ x y z)) '(2 4 6))
12
_$ (apply 'quote '(2 4 6))
; error: bad QUOTE syntax: ((QUOTE 2) (QUOTE 4) (QUOTE 6))
_1$
; reset after error

Obsérvese el error provocado por utilizar la forma especial QUOTE.

Otras muchas funciones LISP requieren argumentos funcionales. Entre las de uso más frecuente
están las funciones de mapeado. MAPCAR, por ejemplo toma dos o más argumentos: una función
y una o más listas (tantas como parámetros requiera la función) y aplica la función sucesivamente
a los elementos de cada lista, devolviendo una lista con los resultados.

_$ (mapcar '+ '(1 2 3) '(10 100 1000))


(11 102 1003)

Otras muchas funciones admiten funciones como argumentos. Entre las más utilizadas tenemos
VL-SORT y VL-REMOVE-IF. La primera es una función de ordenación de uso general. Requiere
una lista y un predicado, y devuelve una lista ordenada pasando sus elementos dos a dos al
predicado.

_$ (vl-sort '(3 2 1 3) '<)


(1 2 3)

VL-REMOVE-IF acepta una función y una lista, y devuelve todos los elementos de la lista para los
cuales la función devuelva NIL (falso).

_$ (vl-remove-if 'numberp '("a" 3 4 "c" 5 "d" "e"))


("a" "c" "d" "e")

El programar nuevas funciones utilitarias que aceptan argumentos funcionales es una parte
importante del estilo de programación funcional que caracteriza a LISP.

FUNCIONES ARITMÉTICAS BÁSICAS


Las funciones aritméticas que tienen como argumento un número devuelven distintos valores
dependiendo de que el argumento proporcionado sea un número entero o real. Si todos los
argumentos son enteros, el valor devuelto será entero. Por el contrario, si alguno o todos los
argumentos son reales, el valor devuelto será un número real. Por ejemplo:
(/ 12 5) devuelve 2, mientras que (/ 12.0 5) devuelve 2.4
Los argumentos de una función aritmética no son necesariamente números. Cualquier otra función
que devuelva un número como resultado es admisible como argumento de una función aritmética.
Ejemplo (* (+ 1 5)(- 20 10))
FUNCIONES BÁSICAS DE TRATAMIENTO DE
CADENAS
Para el tratamiento de cadenas tenemos funciones que permiten unificar cadenas diferentes,
extraer subcadenas de una cadena mayor, determinar cuántos caracteres hay en una cadena y
transformar los caracteres a mayúsculas o minúsculas. El predicado WCMATCH permite determinar
la semejanza de cadenas utiliando comodines.

FUNCIONES BÁSICAS DE ACCESO A LISTAS


Una lista es una manera de representar un conjunto de átomos y de otras listas. Una lista tiene la
forma de un paréntesis de apertura "(" seguido de una serie de átomos o listas, seguido por otro
paréntesis de cierre ")". De manera que cualquier cosa encerrada entre paréntesis será
considerada una lista. Una lista pasada al evaluador LISP será tratada como una expresión
simbólica (S-expresión), es decir, una llamada a función y se considerará el primer término de la
lista como el nombre de la función. Para que una lista sea tratada como dato y no como una
expresión simbólica debe estar contenida en la forma especial QUOTE. Las funciones básicas cuya
comprensión es imprescindible para el acceso a la información contenida en listas se pueden
reducir a cuatro: QUOTE, CAR, CDR, y NTH.

FUNCIONES DE CONSTRUCCIÓN DE LISTAS


Con las funciones del epígrafe anterior podemos descomponer listas, accediendo a
suscomponentes a distintos niveles de anidación. Existen otras funciones que podemos utilizar
para componer nuevas listas a base de elementos individuales, ya sean átomos u otras
listas. CONS, LIST y APPEND son funciones que construyen listas por distintos procedimientos y
con resultados diversos, por lo que es necesario distinguirlas bien.

* Cortés, Ulises y Sierra, Carlos. LISP. Editorial Marcombo, Barcelona-Máxico, 1987. pág. 44
** ibid. pág. 43

2.2.2. Funciones de Acceso a Listas


Existen tres funciones básicas para acceder a los términos de una lista: CAR, QUOTE y CDR.

Funciones CAR y QUOTE:


CAR

CAR admite un único argumento que debe ser una lista o una expresión cuyo valor sea una
lista y devuelve el primer elemento de dicha lista. Como LISP siempre interpreta una lista
como una llamada a una función, necesitamos una manera de pasar una lista a CAR sin
que LISP trate de procesarla como llamada a función.

QUOTE
Con este objetivo se suministra la función QUOTE . Una lista dentro de una
función QUOTE no se tratará de evaluar como llamada a una función. La llamada a la
función QUOTE se puede abreviar utilizando el signo apóstrofe < ’ >.

Funciones CDR y NTH:


CDR recibe también una lista y devuelve el resto de la lista después de eliminar el primer
elemento (CAR lista). Por lo tanto puede contemplarse como la función
complementaria de CAR. Una manera de interpretar una lista en LISP es como la
conjunción de un CAR y un CDR. Se podrá acceder a cualquier término de una lista
mediante los anidamientos apropiados de CAR y CDR.

 (CAR lista) ;primer término


 (CAR (CDR lista)) ;segundo término
 (CAR (CDR (CDR lista))) ;tercer término

y así sucesivamente... Para simplificar las expresiones se permite crear nombres


compuestos para anidamientos de CAR y CDR de la siguiente manera:

 comenzando por una primera letra C


 una letra A por cada CAR o una D por cada CDR
 terminando con una letra R

 así (CAR (CDR (CDR lista))) sería lo mismo que (CADDR lista).

De esta manera podemos construir hasta 28 funciones distintas para acceso a listas.
Según Johnson* estas 28 concatenaciones se pueden dividir en cuatro grupos, tomando
como base la profundidad a que pueden acceder en listas anidadas en varios niveles.

Funciones de acceso al nivel superior:


Funciones de acceso al segundo nivel de anidamiento:
Funciones de acceso al tercer nivel de anidamiento:

Funciones de acceso al cuarto nivel de anidamiento:

Por supuesto, que estas funciones pueden a su vez combinarse para acceder a niveles
aún más profundos de anidación.

NTH

NTH permite simplificar estas expresiones para listas muy largas:

 (nth n lista)

Donde el argumento n es el número del elemento que debe devolverse (cero es el primer
elemento). Si n es mayor que el número de elemento mayor de la lista, NTH devuelve nil .
EJEMPLOS:
De lo antes expuesto resultaría:

_$ (car '(a b c)) ;Caso de una lista normal


A
_$ (cdr '(a b c))
(B C)
_$ (cddr '(a b c))
(D)
_$ (cdddr '(a b c)) ;el último objeto es una lista vacía
nil
_$ (car '(a b . c)) ;Caso en que la lista termina en un par
punteado
A
_$ (cdr '(a b . c))
(B . C)
_$ (cddr '(a b . c))
C ;el último objeto de la lista no es un CONS
_$ (cdddr '(a b . c)) ;lo que provoca un error
; error: bad argument type: consp C
_1$

* Johnson, Nelson. AutoCAD: Manual de Referencia. Osborne/McGraw-Hill, Madrid, 1990. ISBN


84-7615-451-8

2.2.3. Funciones de Construcción de


Listas
Un programa grande suele dividirse en una serie de pequeñas formas o funciones de usuario más
fáciles de implementar y depurar. Las mismas se componen a partir de llamadas a las funciones
primitivas. Estas llamadas tendrán la forma de listas que podrán anidarse unas dentro de otras de
acuerdo a lo que requiera la complejidad de la manipulación que quiera realizarse de los datos
aportados como argumentos. Para la definición de funciones de usuario normalmente utilizaremos
la forma especial DEFUN. Otra manera de representar funciones de usuario son las
expresiones LAMBDA. El estudio de su relación con DEFUN contribuirá a una mejor comprensión
del proceso. La carga de las funciones de usuario guardadas en ficheros se realiza mediante la
función LOAD. Un fichero en que se guarda un programa LISP contiene las distintas formas o
funciones de usuario, una a continuación de la otra, terminando por la función que debe invocarse
para iniciar la ejecución del programa. Esto se debe a que la función LOAD imprimirá en pantalla el
nombre de la última forma evaluada. El nombre de esta función inicial se suele comenzar con los
caracteres "C:" lo que indica al sistema que dicha función de usuario debe tratarse como si fuera
un comando nativo de AutoCAD, en el sentido de que pueda invocarse tecleando el nombre (sin el
prefijo "C:") sin encerrarlo entre paréntesis. Una función de este tipo no admite argumentos en su
lista de parámetros, aunque sí la declaración de variables locales.

2.2.4.1. La Primitiva DEFUN


(defun sím lista-argumentos expresión ...)
DEFUN permite definir una nueva función de usuario con el nombre sím (el nombre de la función se
incluye automáticamente en un QUOTE). Detrás del nombre de la función aparece una lista de
parámetros (posiblemente vacía), con los argumentos a recibir, y que puede estar seguida por una
barra oblicua y los nombres de uno o más símbolos locales (variables locales) que serán definidas
para uso exclusivo de esta función. Esta barra oblicua debe ir separada del primer símbolo local y
del último argumento, si existe, por un espacio como mínimo. Si no declara ningún argumento ni
variable local, se debe incluir una lista vacía tras el nombre de la función. Los argumentos son
tratados como una especie de variables locales en el sentido de que no estarán disponibles fuera
de la función. Los nombres de argumentos deben ser únicos dentro de la misma función.
A continuación de la lista de parámetros se deberán incluir todas las expresiones que deberán ser
evaluadas al llamar a la nueva función de usuario.
A diferencia de muchas funciones primitivas AutoLISP, las funciones definidas por el usuario no
pueden tener argumentos opcionales. Una llamada a una función de usuario debe suministrar
valores para todos los argumentos declarados.
DEFUN no es una función normal, sino lo que se incluye entre las llamadas formas especiales, en el
sentido de que sus argumentos no son evaluados. Lo serán más tarde, al llamar a la nueva
función, sustituyendo sus argumentos por los valores que se desea procesar.
La siguiente expresión define una función llamada DOBLE que devuelve el doble de su argumento
(número real o entero).

_$ (defun doble (x)(* x 2))


DOBLE

Así hemos creado una nueva función Lisp que puede llamarse desde el nivel superior o anidada en
otras funciones:

_$ (doble 1)
2

Un programa Lisp usualmente incluye una colección de tales defuns, asemejándose en ello a un
fichero de definiciones de procedimientos en lenguajes tales como C o Pascal.

Pero, según puntualiza Graham, "algo muy diferente está sucediendo aquí. Las funciones Lisp son
objetos por sí mismas. Lo que realmente hace DEFUN es construir una función y guardarla bajo el
nombre que aparece como primer argumento." Paul Graham, On Lisp, pág. 10

Podemos acceder a la función asociada al símbolo DOBLE utilizando la función Visual LISP vl-
symbol-value:

_$ (vl-symbol-value 'DOBLE)
#<USUBR @045677ac DOBLE>

En versiones anteriores de AutoLISP la función creada con defun era una lista:

Command: (defun doble (x) (* x 2))


DOBLE
Command: !doble
((X) (* X 2))
Command: (car doble)
(X)
Command: (cdr doble)
((* X 2))
En Visual LISP la función de usuario creada con defun es una función compilada que contiene
instrucciones en lenguaje de máquina, por lo tanto en Autocad 2000 obtendremos:

Command: (defun doble (x) (* x 2))


DOBLE
Command: !doble
#<SUBR @01d5ba28 DOBLE>
Command: (car doble)
; error: bad argument type: consp #<SUBR @01d5ba28 DOBLE>
Command: (cdr doble)
; error: bad argument type: consp #<SUBR @01d5ba28 DOBLE>

2.2.4.1.1. Reales a Enteros: Truncamiento


o Redondeo
La función CONS
CONS es el constructor de lista básico. Construye listas insertando elementos en listas existentes
(incluso vacías). El nuevo elemento ocupa el primer lugar de la lista (CAR lista).

(cons nuevo_elemento lista)

El nuevo_elemento puede ser un átomo o una lista.


La función CONS también acepta un átomo en lugar del argumento lista, en cuyo caso construye
una estructura denominada par punteado. El CDR de un par punteado es el segundo término ya
extraído de la lista, es decir, sin los paréntesis.
Ejemplo: (cons 'a 'b) devuelve (A . B) y (cdr '(a . b)) devuelve B.

Debe tenerse en cuenta que CONS, al igual que casi todas las funciones LISP es una función no
destructiva, es decir que no altera los argumentos que recibe. Así que para conservar la lista con el
nuevo primer elemento, será necesario utilizar SETQ. La función más general para incorporar
nuevos elementos a una lista sería entonces:

(setq nombre_lista (cons nuevo_elemento nombre_lista))

donde nombre_lista sería el símbolo asociado al objeto lista. la función opera


aunque nombre_lista no hubiera sido previamente asociado a una lista, pues no debemos
olvidar que un símbolo no asociado se evalúa como NIL, que es, a su vez, equivalente a una lista
vacía.
Ejemplo:

_$ (cons 'a 'b)


(A . B)
_$ (cons 'a (cons 'b (cons 'c '())))
(A B C)
_$ (cons 'a '(b c d))
(A B C D)

Funciones de ejemplo usando CONS/CAR/CDR


La función LIST
(list expr ...)

LIST Recupera cualquier número de expresiones y las combina en una lista. Admite tanto átomos
como listas. Si uno de los agumentos es una lista vacía NIL aparecerá como uno de los términos
de la lista.
Ejemplo:

_$ (list 3 4 'a (car '(b . c)) (+ 6 -2))


(3 4 A B 4)
_$ (list (list 'a 'b) (list 'c 'd 'e))
((A B) (C D E))

La función APPEND
(append lista lista ...)

APPEND Se utiliza para combinar listas. Elimina el primer nivel de anidación de cada una de las
listas que recibe para combinar todas en una misma lista. Si una de las listas que recibe está vacía
esta lista no aparecerá en la lista resultante.
Ejemplo:

_$ (append '(a b c) '(d e f) '() '(g))


(A B C D E F G)

Una muestra de la utilización de APPEND para eliminar las sublistas vacías:

_$ (apply 'append '(("M") ("a") nil ("r") ("i") nil))


("M" "a" "r" "i")

2.2.3.1. Ejemplos con CONS, CAR y CDR


;;;Funciones de ejempo usando CONS/CAR/CDR
;;;Cambia el primer término de lista2 por el de lista1
(defun permutainicio (lista1 lista2)
(cons (car lista1) (cdr lista2))
) ;_ fin de defun

;;;Elimina el primero y el último término


(defun recortalista (lista)
(reverse (cdr (reverse (cdr lista))))
) ;_ fin de defun

;;;Predicado Palindrome-p
;;;Comprueba si una lista es igual
;;;leída de izquierda a derecha o al revés
(defun palindrome-p (lista)
(equal lista (reverse lista))
) ;_ fin de defun

;;;Posición en lista
(defun posicion (termino lista)
(if (member termino lista)
(- (length lista) (length (member termino lista)))
nil
) ;_ fin de if
) ;_ fin de defun

También podría gustarte