Mostrando entradas con la etiqueta curso lisp. Mostrar todas las entradas
Mostrando entradas con la etiqueta curso lisp. Mostrar todas las entradas

jueves, agosto 12, 2010

Lectura y Escritura en Lisp II

Hola otra vez,

Siguiendo el post anterior, continuamos con la pregunta que nos hacía un lector de este blog en esta entrada: http://aitoreus.blogspot.com/2007/10/lisp-1-leccin.html


Vamos a hacer el típico programa que nos dice si un número es primo o no.

Primero lo haremos de la forma habitual en Lisp, que es como me lo he encontrado en el foro de Ubuntu. Programando de esta forma no hace falta que utilicemos ninguna función de entrada-salida:




Yo utilizo el editor VIM porque me reconoce la sintaxis de cualquier lenguaje de programación.



Como véis lo único que hacemos es definir la función isprime().

Una vez que tengamos el Common Lisp instalado haremos lo siguiente:

1.-Botón derecho sobre el fichero de texto ISPRIME.LSP

2.-Seleccionar "COMPILE WITH CLISP".

3.-Botón derecho sobre el fichero que se ha generado ISPRIME.FAS

4.-Seleccionar "LOAD INTO CLISP".


De esta forma se carga en Clisp y podremos ejecutar... isprime pasándole el número que queremos comprobar:


Siguiendo las convenciones de Lisp la función devuelve T (true) si el número es primo y NIL (false o lista vacía) si no es primo.


Y ahora lo que me preguntaban... Cómo hacer una ejecución limpia donde sea el programa el que nos pregunte por el número.


Pues el programa adaptado quedaría así:



Hemos añadido un print, un read, una asignación de la entrada a una variable.

La diferencia es que ahora podemos ejecutarlo directamente sin cargar en CLisp la función.

Se haría dando al botón derecho sobre el fichero ISPRIME2.FAS y haciendo clic en "EXECUTE WITH CLISP".


Nota: he puesto al final una llamada a la función READ-LINE para que antes de cerrarse la ventana podamos ver el resultado. En cuanto le metes un ENTER se cerrará la ventana.


Saludos.

martes, agosto 03, 2010

Lectura y escritura en Lisp

Hola,
En una entrada antigua del 30/10/2007 me preguntan en la sección de comentarios cómo sería un programa lisp que recoja datos desde el teclado.

Ahora es tarde. Mañana pondré algún ejemplo útil. Ahora vamos a ver cómo sería la teoría.

Lo primero bajar el COMMON LISP que es "el Lisp que hay que aprender". El sitio es este: http://clisp.cons.org/

y yo me lo he bajado de aquí para Windows: http://sourceforge.net/projects/clisp/files/clisp/2.49/clisp-2.49-win32-mingw-big.exe/download

En teoría con las primitivas PRINT, READ y FORMAT debería ser suficiente.

PRINT: evalúa el argumento que le pasamos y lo imprime.

(setf velocidad 120)
(print velocidad)

READ: Cuando el intérprete encuentra esta primitiva se queda a la espera de que tecleemos algo. Read no imprime nada por lo que habrá que usar PRINT para hacer la pregunta de marras.

(print '(Introduce tu nombre chavalote))
(setf nombre (read))

FORMAT: Esta primitiva permite más opciones que PRINT por medio del uso de directivas. Como os decía mañana lo aclaramos con un ejemplo.

Saludos.

miércoles, noviembre 21, 2007

Lisp, por fin algo útil y potente como la recursividad

¿Que es la recursión, o recursividad?

Podemos decir que es una forma de resolver problemas.

Si analizamos un problema, y descubrimos que se puede resolver por partes en las que se vuelve a plantear el problema original pero de forma más "reducida", entonces podemos resolver por recursión.

Ya veis que es algo dificil de explicar, pero se puede ver muy fácilmente.

El ejemplo típico es la función factorial.

El factorial de 6 se representa: 6! y es igual a 6 x 5 x 4 x3 x 2 x 1. Por lo tanto 6! = 720.

Si nos fijamos un poco podemos ver que el factorial de 5 es igual a 5 x 4 x 3 x 2 x 1.

Por lo tanto el factorial de 6 es igual a 6 x el factorial de 5.
Y el factorial de 5 es igual a 5 x el factorial de 4.
etc. etc.

Por convenio en matemáticas el factorial de 0 es igual a 1.

Vemos que podemos usar la función factorial al intentar calcular el factorial de un número.

Función factorial recursiva:

(defun factorial (n)
(if (zerop n) 1
(* n (factorial (1- n)))
)

)

Explicación de la función:

El factorial de un número n es:
1-Si n = 0 entonces el factorial es 1.
2-Si n no es 0, entonces el factorial es n x factorial(n-1)

Avisos:
La función (1- n) devuelve el número n menos 1.
Existe la función (1+ n) que devuelve el número n más 1.

martes, noviembre 20, 2007

Lisp, carga de programas .lsp

Se que os recomendé un interprete lisp llamado clisp.

Bueno pues hoy si queréis podéis probar este otro, que al menos tiene más logrado el interfaz gráfico para windows. Probarlo y me entenderéis...

Se llama XLisp-Plus y se encuentra en http://almy.us/xlisp.html.

XLisp es un Lisp basado en Scheme (uno de los dialectos de Lisp). Lo que ocurre es que no se distribuye XLisp en formato ejecutable, por lo que he preferido bajarme el XLisp-Plus.

Bueno, bajamos el intérprete y la documentación.

Los descomprimimos y colocamos los ficheros resultantes donde más nos interese tenerlos.

Vamos a la carpeta donde se encuentra el ejecutable xlwin32 y creamos un fichero que llamaremos hola-mundo.lsp. Editamos el fichero y escribimos:

(print ‘”Hola mundo”)

Cerramos y guardamos el fichero.

Ahora entramos en el interprete Lisp haciendo doble clic en xlwin32.exe.

Para cargar y ejecutar un fichero lisp (tiene extensiones .lsp) hacemos lo siguiente:

(load ‘hola-mundo.lsp)

> “Hola mundo”
> “Hola mundo”


La función print muestra en pantalla el string que le hemos pasado como argumento, pero a su vez devuelve un valor que es la evaluación del argumento. Por eso el mismo string aparece dos veces.

Bueno, pues ya estamos preparados para escribir programas LISP.

Saludos a tod@s,

viernes, noviembre 16, 2007

Lisp, quinta lección

Bueno, por fin tenemos elementos suficientes para empezar a utilizar Lisp.

De todas formas, vamos a ver primero las funciones CONDICIONALES.

IF

(if expresion expresion)
Es el típico if...then de otros lenguajes.

En este caso se evalúa el primer argumento. Si el valor es distinto a NIL entonces se evalua el segundo argumento y el valor devuelto es lo que devuelve la función IF.

(if (listp '(a)) 'LISTA)
> LISTA

(if (listp 'a) 'LISTA)
> NIL

(if expresion expresion expresion)
Es el típico if...then...else de otros lenguajes.

Si el valor del primer argumento es T entonces se evalúa el segundo argumento. Si no es así se evalúa el tercer argumento.

(if (listp '(a)) 'LISTA 'NO-LISTA)
> LISTA

(if (listp 'a) 'LISTA 'NO-LISTA)
> NO-LISTA

WHEN

Es igual que la función IF.

(when expresion expresion) es equivalente a (if expresion expresion).

UNLESS

Esta función es un poco dudosa y también prescindible igual que WHEN.

(unless expresion expresion)
Si el valor del primer argumento es falso se devuelve el valor del segundo argumento.
Si el valor del primer argumento es verdadero devuelve NIL.

Es totalmente equivalente a (if expresion NIL expresion).

COND

Parecido a la instrucción SELECT CASE de otros lenguajes.
Es como un montón de if...then...else.

(cond (expresion-test1 expresion-consecuencia1 expresion-consecuencia2...)
(expresion-test1 expresion-consecuencia2 expresion-consecuencia2...)
....
(t expresion-consecuenciaN expresionconsecuenciaN+1........)
)

La última claúsula (la de t) no es obligatoria.
Si no se cumple ninguna expresion-test de cond se devuelve NIL.

miércoles, noviembre 14, 2007

Lisp, 5ª lección

Funciones predicado

Me imagino (no tengo mis apuntes a mano) que se llaman así porque sirven para obtener información de los predicados, o sea, de sus argumentos.

Creo que esta es la última lección que necesitamos antes de empezar a resolver problemas. Bueno, esto no es del todo exacto. Necesitamos también funciones para el control de flujo (for, while y esas cosas).

¿Qué devuelven las funciones predicado?

Devuelven el símbolo t para indicar que se cumple la condición (t de true).

Devuelven el símbolo NIL para indicar que la condición no se cumple. NIL es un símbolo y una lista a la vez: la lista vacía.

NIL = ()

Por eso (rest ‘(a)) devuelve NIL, o sea la lista vacía.

Por cierto, la mayoría de las funciones predicado terminan con la letra P (de predicado).

Función SYMBOLP

Sirve para saber si el valor del argumento es un símbolo o no.

(symbolp NIL)
> t


(symbolp t)
> t


(symbolp (first '(a b)))
> t


Función LISTP

Indica si el valor del argumento es una lista.

(listp ‘(a b c))
> t

(listp NIL)
> t


Función NUMBERP

(numberp 5)
> t

Función ATOM

Los símbolos y números son átomos.

(atom 'a)
> t

(atom 5)
> t

(atom '(a))
> NIL

Función ZEROP

Indica si el valor del argumento es cero o no.

Función MINUSP

Para saber si el valor del argumento es negativo.

Función PLUSP

Para saber si el valor del argumento es positivo.

Función EVENP

Nos dice si es par.

Función ODDP

Para saber si es impar.

Función "<" (menor)

(<>
> NIL

(<>
> t

Función ">" (mayor)

(> 7 6 5)
> t

Función "=" (igualdad)

(= 4 4)
> t

(= 4 4.0)
> t

(= 4 (first '(4 2)))
> t

Función EQ

Similar a la función "igualdad", pero los valores de los argumentos tienen que ser símbolos.

(eq 'a (first '(a b)))
> t

(eq 'a (rest '(a b)))
> ERROR.

Función EQL

Similar a los 2 anteriores, pero los valores de los argumentos tienen que ser números o símbolos.

(eql 'a (first '(a)))
> t

(eql 4 4.0)
> NIL por ser diferentes números (uno entero y otro decimal).

Función EQUAL

Sirve para números, símbolos y listas. En el caso de los números el comportamiento es igual que en la función EQL.

(equal '(a b 4) (list 'a 'b 4.0))
> NIL

Bueno, ya está bien por hoy.
Saludos...

lunes, noviembre 12, 2007

Lisp, 4ª lección, segunda parte

Bueno, y ahora hablemos un poco de funciones superfluas.

LET*

Si nos fijamos un poquito nos damos cuenta de que...
Se puede sustituir LET* por un LET dentro de otro LET:

Si hacemos

(let ( (x 100)
)
(let ( (y (+ x 200)))
)
)




Comprobamos que es totalmente equivalente a...



(let* ( (x 100)
(y (+ x 200))
)

)


¡Ja! así que podemos prescindir de LET* tranquilamente.

Hay muchas otras funciones prescindibles.

Por ejemplo la función SECOND.

Second sirve para elegir el segundo elemento de una lista.



(second '(a b c)
> b



En la primera lección de Lisp vimos las funciones FIRST y REST.

Podemos definir una nueva función llamada SEGUNDO.



(defun segundo (lista)
(first (rest lista))
)




(segundo '(a b c))
> b



De esta forma podemos hacer nuestro propio LISP fácilmente.

4ª Lección de Lisp

Bueno, hoy toca intensivo,

Primero 2 funciones que pueden venir bien en cualquier situación:

LENGTH

(length lista)
Devuelve el número de elementos de la lista.

(length ‘(a b c))
> 3

REVERSE

(reverse lista)
Devuelve la misma lista pero invierte el orden.

(reverse ‘(a b c))
> (c b a)


Y dos funciones muy importantes en lisp:

LET

Esta función permite hacer asignación de variables de forma local.
Se ve claro en el siguiente ejemplo.



(setf a ‘HOLA)
(setf b ‘ADIOS)
(let ( (a 6)
(b 9)
)
(+ a b)
)
> 15
a
> HOLA
b
> ADIOS



Esto es, dentro del cuerpo del LET las variables tienen el valor que se ha preasignado, y no tiene que ver con el valor que tenían fuera de ese ámbito.

LET*

Es muy similar a LET, pero con el asterisco la asignación es dinámica. ¿Que significa esto? Veámoslo con otro ejemplo:



(let (
(x 100)
(y (+ x 200))
)
)



Esto devuelve un error si se hace con la función LET. Es porque cuando intenta asignar un valor a “y”, “x” todavía no tiene un valor válido.
En cambio si utilizamos LET*, primero asigna el valor a “x” y luego a “y”, de forma que no se produce un error.

jueves, noviembre 08, 2007

Lisp, 3ª lección

Hoy voy a improvisar un poco porque no tengo los apuntes a mano.

Para empezar a hacer algo con Lisp vamos a necesitar un mínimo de operaciones aritméticas.

Funciones matemáticas básicas en Lisp:

La útil suma:

(+ 7 37 39 2)
Devuelve 85.

La imprescindible resta:
(- 7 37 39 2)
Devuelve -71.

¡Ah!, entonces como habréis imaginado...

La multiplicación:
(* 6 6)
Devuelve 36.

Y
(/ 36 6)
Devuelve 6.

Ahora otras funciones algo más complejas (pero poco):

(mod 36 6)
Devuelve 0 por ser el resto de la división.

Entonces,
(mod 37 6)
Devuelve 1.

La raiz cuadrada:

(sqrt 25)
Devuelve 5.

Y por si alguien tiene dudas:
(sqrt 91)
Devuelve 9.539392.

Ahora unas funciones de lo más prescindibles:
(max 7 37 39 2) devuelve el máximo valor.
Por lo tanto devuelve 39.

(min 7 37 39 2) devuelve el mínimo valor.
Por lo tanto devuelve 2.

(abs -2) devuelve el valor absoluto.
Por lo tanto devuelve 2.

¿Por qué digo que son funciones prescindibles?
Porque son fácilmente implementables en Lisp.

Veamos como...

Para definir funciones en lisp utilizamos la función defun.

Voy a crear una función con el nombre suma que servirá para sumar 2 argumentos.
(defun suma (argumento1 argumento2)
(+ argumento1 argumento2)
)


Cuando terminemos de meter las 3 líneas en el interprete nos devolverá el prompt de Lisp. Ahora la función se encuentra cargada en memoria y podemos utilizarla.

(suma 45 5)
Devolverá 50.

¡Que útil!
Ya podemos ampliar Lisp con nuevas funciones.

martes, octubre 30, 2007

Lisp. 1ª lección

Lo primero la descarga del interprete.

Lo mejor es descargar una implementación del ANSI Common Lisp. En el siguiente enlace podremos seleccionar un ejecutable adecuado para nuestro Sistema Operativo:

http://clisp.cons.org/ Seleccionar SourceForge download.

La versión de Clisp que me he bajado es la 2.42. Ocupa algo menos que 8 Mbytes.

Descomprimimos el contenido y ejecutamos clisp.exe

El interprete nos contestará con el prompt:

>

Ahora un poquito de teoría:

Tipos de datos en Lisp:

Átomos: símbolos y números. Por ejemplo: 5, 6, a, persona, aula_5

Listas. Por ejemplo: (5 a 7 5)


Como separadores se permiten el espacio y el tabulador.

Las expresiones Lisp se evalúan en el momento y se devuelven un resultado.

Los números se evalúan a si mismo.

Por lo tanto >5 devuelve 5.

Las funciones son de 2 tipos: primitivas de Lisp o las definidas por el usuario.

La notación siempre es prefijo. Primero se indica la función y luego se pasan los argumentos.

(funcion arg1 arg2)


Evalación en Lisp:

Cuando Lisp detecta un paréntesis izquierdo espera encontrar un nombre de función. Si no es así devuelve un error.

>(+ 500 300)

Devuelve 800.

(* 3 4)

Devuelve 12.

Variables:

Setf es una función primitiva especial.

>(setf simbolo expresion)


Si no hay error se asigna el valor de la expresión al símbolo.

Además Lisp devuelve el valor de la expresión.


>(setf a 5)

Devuelve 5.

Setf permite múltiples parejas:

>(setf var1 8

var2 15

var3 5000)

En un caso así devuelve el último valor: 5000.

Evaluación de variables:

>Var2

Devuelve 15.

Quote es otra función especial.

Consigue que las expresiones no se evalúen.

(quote expresion)

(quote Carlos)

Devuelve Carlos pero sin evaluar.

>(setf var1 (quote a))

Devuelve a.

> var1

Devuelve a.


FUNCIONES DE SELECCIÓN


(first lista)

Devuelve el primer elemento de la lista.


(rest lista)

Devuelve la lista quitándole el primer elemento.


(nth entero lista)

Selecciona el elemento de la lista especificado por el número.

(nth 1 (quote (a (b c) d e )))

Devuelve (b c)

(nthcdr entero lista)

Devuelve la lista que queda al eliminar por delante tantos elementos como indica el entero.

(last lista)

Devuelve la lista que contiene al último elemento.

(butlast lista)

Coge toda la lista menos el último elemento.

En lugar de quote se puede sustituir por el carácter reservado comilla: ‘.

(quote xxxx) equivale a ‘xxxx

Bueno, ya está bien por hoy.
Mañana la segunda lección y el planteamiento del primer problema típico de la asignatura "Inteligencia Artificial".