Mas Funciones en LISP





Anteriormente se dieron a conocer los comandos básicos de LISP, en esta parte se darán a conocer más a fondo las funciones clasificadas desde otro punto de vista.

Funciones aritméticas y asignación de valor

 

Las funciones aritméticas básicas del LISP son:

 

PLUS DIFFERENCE TIMES QUOTIENT
SETQ

SET

ADD1 SUB1

 

Las cuales se abrevian en la mayoría de los sistemas mediante los familiares signos +, -, * y /. Todas estas funciones tienen cero o más operandos, o argumentos, y se escriben en la forma prefija como las otras funciones del LISP. Cuando se combinan para formar el equivalente a las expresiones aritméticas, estas funciones están completamente puestas entre paréntesis y, por tanto, no hay necesidad en LISP de definir ninguna precedencia jerárquica entre ellos.

Para ilustrar esto, supongamos que H, I, N y X son variables en LISP. Las expresiones algebraicas mostradas en la parte de la izquierda (que es como se escribirían en otros lenguajes) se escriben en LISP como se muestra a la derecha:

 

EXPRESION FORMA EN LISP
H + 2 (+ H 2)
H + 2 + I    (+(+H 2)I)
H + 2 * I    (+H(*2 I))
SUM(X)/N     (/(SUM X)N)

 

Puesto que las formas en LISP están completamente encerradas entre paréntesis, su orden de evaluación es siempre explícito. El segundo ejemplo supone que la evaluación es de izquierda a derecha para las operaciones con la misma precedencia, mientras que el tercero supone que «*» tiene precedencia sobre «+» en las expresiones de la izquierda. El cuarto ejemplo ilustra la aplicación de una función definida par el programador en el contexto de una expresión mayor.

La  asignación  del  valor  de  una  expresión  a  otra variable se realiza por la función «setq» o la función «set». Estas funciones tienen dos operandos:

 

(setq variable expresión) (set ‘variable expresión)

 

En cualquiera de las dos, «variable» es el nombre de una variable que es el destino de la asignación y «expresión» es una lista cuyo resultado se asignará a la variable. Por ejemplo, la función

 

(setq I (+ I 1))

 

Es equivalente a la familiar forma I := I + 1 en Pascal. Se evalúa primero la expresión de la derecha y el resultado se asigna a la variable

 

I. En general, este resultado puede ser un átomo (un número o un símbolo) o una lista, como veremos en posteriores ejemplos.

 

Las funciones unarias «addl» y «subl» se dan en LISP para simplificar la especificación de la común operación de sumar o restar 1 del valor de una variable. Esta operación se encuentra en todas Las aplicaciones de programación y es especialmente frecuente en la programación recursiva.

 

 

Comilla (‘) y Evaluación

 

La comilla (‘), la letra q en setq y la función «quote» se utilizan en LISP para distinguir explícitamente entre expresiones evaluadas. Esta distinción se necesita debido a la naturaleza dual de un símbolo en LISP en algunos contextos: su uso como un ítem de dato y su uso como un nombre de variable. Si «E» denota cualquier expresión en LISP entonces su aparición dentro de un programa implica normalmente que va a evaluarse inmediatamente y que el valor resultante se utilizará a continuación. Sin embargo, la expresión

 

(quote E)

 

Que normalmente se abrevia como ‘E, denote que E permanece por si misma

y que no va a ser evaluada.

Por ejemplo, consideremos las siguientes dos expresiones, en donde X se va a usar como variable (en la izquierda) y como un valor literal (en la derecha):

 

COMO VARIABLE COMO LITERAL
((SETQ X 1)(SETQ Y X)) ((SETQ X 1)(SETQ Y ‘X))

 

En la expresión de la izquierda, a las variables X e Y se les asigna a ambas el valor 1. En la expresión de la derecha, a X se le asigna el valor I y a Y se le asigna el valor (literal) X. El último es, en efecto, una cadena de caracteres de longitud 1 o un átomo no numérico.

Esto  ayuda  a  explicar  la  diferencia  entre  «set»  y

«setq» del párrafo anterior. «Setq» es solo una forma conveniente de

combinar «set» con un primer argumento con comilla. Es decir, el nombre de la variable de la izquierda de una asignación no debe ser evaluado; designa una dirección en vez de un valor. Por tanto, las tres formas siguientes son equivalentes:

 

(setq X 1)

(set,X 1)

(set (quote X) 1)

 

En  la  práctica  se  prefiere  normalmente  la  primera forma; la tercera es el precedente histórico de las otras dos.

 

Funciones de manipulación de Listas

 

La principal fuerza del LISP consiste en su potencia para manipular expresiones simbólicas en vez de expresiones numéricas. Para ilustrar esto, supongamos que tenemos una lista L compuesta de los nombres de nombres de lenguajes de programación. Esto es,

 

L = (pascal, fortran, cobol, pli)

 

sentencia:


El valor de L puede ser asignado mediante la siguiente

 

(setq L ‘(pascal fortran cobol pli))

 

Observe aquí que la comilla (‘) fuerza a que se trate a la lista de lenguajes como un literal, en vez de como una colección de variables denominadas «pascal», «fortran», etc.

Recuerde que, en general, una lista puede ser nada, un átomo o una serie de elementos entre paréntesis (e1 e2 … en).





Las dos funciones básicas vistas anteriormente, «car» y «cdr», se utilizan para dividir listas (es decir, sus representaciones subyacentes) en dos partes. «Car» define al primer elemento, e1, de una lista y «cdr» define a la lista que comprende el resto de los elementos (e2 … en). En el caso especial en que n=1, la cdr se define como nada. Cuando la lista original es un átomo simple o nada, Las funciones car y cdr producen valores indefinidos y se producirá un error en tiempo de ejecución. (Algunas implementaciones son una excepción y definen a car y cdr como nada en este caso especial. Este compromiso simplifica algunas veces la programación de las situaciones «límites», aunque sacrifica la consistencia y transportabilidad.) Ejemplos de aplicación de estas funciones se pueden ver en la primera parte de este apunte.

Algunas de las múltiples aplicaciones de las funciones car y cdr pueden abreviarse en LISP con los siguientes criterios:

 

FUNCION                     RESULTADO
(CAR (CDR L))

(CADR L)

(CDR(CAR L))

(CDAR L)

(CAR(CAR .. (CAR L).. ))) (CAA .. AR L)
(CDR(CDR .. (CDR L).. ))) (CDD .. DR L)

 

Recuerden que todas estas aplicaciones son en el contexto de la construcción de funciones.

Algunas implementaciones del LISP limitan el grado de anidamiento que puede abreviarse de esta forma. Sin embargo, para la mayoría de las implementaciones pueden asumirse con seguridad al menos tres niveles.

En  contraste  con  la  división  de  una  lista  en  sus constituyentes está la función de construir una lista a partir de otras listas. Esto se realiza en LISP mediante las siguientes funciones. En esta descripción, e1, e2, …, son términos cualesquiera.

 

FUNCION               SIGNIFICADO
(CONS e1 e2) YA VISTA.
(LIST e1 e2 .. en) Construye una lista de la forma (e1 e2 .. en.
(APPEND e1 e2 .. en) Construye una lista de la forma (f1 f2 .. fn), donde cada f es el resultado de quitar los paréntesis exteriores de cada e. Aquí los términos e no pueden ser átomos.

 

Para ilustrar el uso de estas funciones, reconsideremos la lista L cuyo valor es (pascal fortran cobol pli). Si necesitamos construir una nueva lista M, cuyos elementos sean los de la lista L y los de la nueva lista (snobol apl lisp), podemos escribir lo siguiente:

 

(setq M (list L ‘(snobol apl lisp)))

 

El valor resultante de M es:

 ((pascal fortran cobol pli) (snobol apl lisp))

 

la cual es una lista de dos elementos, no de siete.

Por otra parte, como ya vimos, «cons» tiene siempre dos argumentos. Por tanto,

 (cons ‘snobol (cons ‘apl (cons lisp nil)))

 

construye la lista

 (snobol apl lisp)

 Por tanto, esta lista podría haberse construido de forma equivalente mediante la siguiente función:

 (list ‘snobol ‘apl ‘lisp)

 «Append» es alga diferente de «list», en el sentido de que necesita que sus argumentos sean listas encerradas entre paréntesis y ella quite dichos paréntesis para construir el resultado. Por tanto,

 

(append L ‘(snobol apl lisp))

 

da la lista de siete elementos:

 

(pascal fortran cobol pli snobol apl lisp)

 

la cual es estructuralmente distinta de la lista M formada en el anterior ejemplo .

Finalmente, se añaden a este grupo de funciones las resumidas  en  la  tabla  siguiente.(Todas  ellas  usan  como  parámetros términos, se debe verificar que parámetros son restringidos a solamente listas.)

 

FUNCION             SIGNIFICADO

 

(RPLACA e1 e2)      Reemplaza el car de e1 por e2.

 

(RPLACD e1 e2)      Reemplaza el cdr de e1 por e2.

 

(SUBST e1 e2 e3)    Reemplaza cada instancia de e2 en e3 por (el sustituto) e1.

 

 

(REVERSE (e1 e2 ..

en))

 

(LENGTH  (e1  e2  ..

en))

 

Invierte los elementos de la lista formando (en.. e2 e1).

 

El número de términos de la lista n.

En las funciones «rplaca» y «replacd», el argumento e1
debe denotar una   lista   puesta   entre   paréntesis, para   que   las

correspondientes  car  y  cdr  queden  bien  definidas.  Igualmente,  el

argumento e3 de la función «subts» debe ser también una lista encerrada entre paréntesis.

Para ilustrar esto, supongamos de nuevo que tenemos las listas L y M, con los valores respectivos (pascal fortran cobol pli) y ((pascal fortran cobol pli)(snobol apl lisp)). Las siguientes expresiones conducen a los resultados mostrados a la derecha:

EXPRESION            RESULTADO
(RPLACA L ‘MODULA) (MODULA FORTRAN COBOL PLI)
(RPLACD M ‘PROLOG) ((PASCAL FORTRAN COBOL PLI)PROLOG)
(REVERSE (CARD M)) (LISP APL SNOBOL)
(SUBST ‘ADA ‘PLI L) (PASCAL FORTRAN COBOL ADA)
(LENGTH L) 4
(LENGTH M) 2

 





También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *