Translate

Mostrando entradas con la etiqueta listas. Mostrar todas las entradas
Mostrando entradas con la etiqueta listas. Mostrar todas las entradas

domingo, 26 de noviembre de 2017

Funciones (devolver valores)

Es muy sencillo, la función creada devolverá el último valor que se llama. Un ejemplo:

(defun maximo (a b)
    (if (> a b) (setf max a)
                     (setf max b))

    max)

Se puede devolver cualquier tipo de valor, según los tipos de variables que soporta el common lisp. Para utilizar el valor devuelto por la función:

(setf el-maximo (maximo 2 7)

Ahora bien, y observen la potencia del lenguaje, si quiero devolver múltiples valores, me conviene devolver una lista, que es un tipo nativo de nuestro lisp. Un ejemplo, en las ecuaciones de segundo grado hay dos raices posibles:


(defun segundo-grado (a b c)  ;ax^2 + bx + c = 0


    (setf det (- (expt b 2) (* 4 a c)))

    (setf x1 (/ (+ (- 0 b) (sqrt det))
                     (* 2 a)))
    (setf x2 (/ (- (- 0 b) (sqrt det))
                     (* 2 a)))

    (setf raices list x1 x2)
    raices)

Y devuelve una lista con dos elementos. Para usar los valores devueltos por esta función:

(setf lista (segundo-grado 1 2 3))
(setf x-1 (first lista))
(setf x-2 (second lista))
Que nos devuelve dos valores complejos para este caso.

Si una función devuelve múltiples valores en una lista, supongamos que devuelve ocho por ejemplo, debemos obtener los valores devueltos usando la función nth.





 

sábado, 6 de septiembre de 2014

Listas de propiedades




Las listas de propiedades son parecidas a los registros en otros lenguajes. Lo que se llama "campos" para otros lenguajes en common lisp son propiedades.

Veamos unos ejemplos:

> (setf pelota '(:color "blanco" :diametro 25 :material "cuero"))

Pelota tiene distintas propiedades como color diámetro y material. Veamos otro:

> (setf mi-moto '(:marca "Zanella" :modelo "Custom Patagonian Eagle" :cilindrada 150 :kilometros 4000 :precio 12000))
(:MARCA "Zanella" :MODELO "Custom Patagonian Eagle" :CILINDRADA 150 :KM 4000 :PRECIO 12000)


Para obtener el valor de una propiedad, usamos la función getf:

> (getf mi-moto :modelo)
"Custom Patagonian Eagle"

La función getf nos devuelve el valor de la propiedad, para ser utilizadas como argumento de otra función o almacenarse en un símbolo (de todas formas, al almacenarse termina usándose como argumento de otra función: "setf")

> (setf modelo (getf mi-moto :modelo))

En modelo queda el valor "Custom Patagonian Eagle".

Para modificar un valor de la lista de propiedades usamos "setf" con "getf" a la vez. Supongamos que queremos modificar el precio de "mi-moto":

> (setf (getf mi-moto :precio) 13000)
13000

Ok! :-P Si consultamos ahora nuestra lista de propiedades, veremos:

> mi-moto
(:MARCA "Zanella" :MODELO "Custom eagle" :CILINDRADA 150 :KM 4000 :PRECIO 13000)

Se puede guardar cada lista de propiedades en una lista, para tener una base de datos sencilla, que podría guardarse en un archivo, y tener funciones para búsqueda y filtros, etc. Las posibilidades son infinitas.

sábado, 4 de mayo de 2013

Mas tipos de datos lisp



Listas de Propiedades


Las listas de propiedades (‘plistas’) proporcionan una vía simple pero poderosa de manejar pares de palabras-clave/valores. Una plista es simplemente una lista, con un número par de elementos, donde cada pareja de elementos representa un valor con nombre. Este es un ejemplo de plista:

   > '(:nombre "Gloria" :domicilio "Calle Urquiza 1222, Formosa" :celular "111-111111" :edad 35)

En esta plista, las claves son símbolos de palabras clave, y los valores son cadenas. Las claves en una plista son con mucha frecuencia símbolos de palabras clave. Los símbolos de palabras clave son símbolos cuyos nombres van precedidos por un signo de dos puntos (‘:’), y que son usadas generalmente justo para comparar el símbolo en sí (típicamente no se usan por su valor del símbolo o función del símbolo). Para acceder a los miembros de una plista, CL proporciona la función getf, que toma una plista y una clave:

   > (getf '(:nombre "Gloria" :domicilio "Calle Urquiza 1222, Formosa" :celular "111-111111" :edad 35) :nombre)
   "Gloria"

Es mas cómodo guardar la lista de propiedad en una variable:

   > (set 'registro '(:nombre "Gloria" :domicilio "Calle Urquiza 1222, Formosa" :celular "111-111111" :edad 35))

   > (getf registro :edad)
   35


 

 

 

 

 

 

 

 





 "Oh, Lisp me vuelve tan loca..." (Ai Sayama)

 

 

 

Arrays (Arreglos)


Los arreglos son estructuras de datos que pueden albergar "rejillas" simples (o multi-dimensionales) llenas de valores, que son indexadas por uno o más enteros. Los arreglos soportan un acceso muy rápido a los datos basado en índices de enteros. Se crean arreglos empleando la función constructora make-array y los elementos del arreglo se refieren usando la función de acceso aref. Se pueden establecer elementos individuales en el arreglo usando setf:

     > (set 'array (make-array (list 3 3)))
     #2A((NIL NIL NIL) (NIL NIL NIL) (NIL NIL NIL))
    
     > (setf (aref array 0 0) "David")
     "David"
    
     > (setf (aref array 0 1) "José")
     "José"
    
     > (aref array 0 0)
     "David"
    
     > (aref array 0 1)
     "José"

Observe que luego de la función va el argumento requerido de las dimensiones del array, que debe ser una lista. En el ejemplo anterior se trata de un array de 3 * 3. La función make-array también admite varios argumentos de palabras clave optativos para inicializar el arreglo en el momento de su creación. Uno de ellos es :initial-contents que permite establecer los valores iniciales:

    > (make-array '(4 2 3)
            :initial-contents
            '(((a b c) (1 2 3))
              ((d e f) (3 1 2))
              ((g h i) (2 3 1))
              ((j k l) (0 0 0))))
    #3A(((A B C) (1 2 3)) ((D E F) (3 1 2)) ((G H I) (2 3 1)) ((J K L) (0 0 0)))

Se trata de un array de tres dimensiones: 4 * 2 * 3.
Observe la respuesta del intérprete al crear el array: Comienza con las dimensiones #3A (A es el tipo del array) y luego los elementos como listas anidadas. De esta manera podríamos definir al array sin usar la función make-array:

   > (set 'nuevo-array #3A(((a b c) (1 2 3)) ((d e f) (3 1 2)) ((g h i) (2 3 1)) ((j k l) (0 0 0))))

   > (aref nuevo-array 2 0 1)
   H

   > (setf (aref nuevo-array 3 1 1) "sapo pepe")
   "sapo pepe"

   > nuevo-array
   #3A(((A B C) (1 2 3)) ((D E F) (3 1 2)) ((G H I) (2 3 1)) ((J K L) (0 "sapo pepe" 0)))

Tablas Hash


Una tabla hash es similar a lo que en otros lenguajes es conocido como arreglo asociativo. Es comparable a un array de una dimensión que admite claves que son cualquier objeto CL arbitrario, que serán comparados usando eql. Las tablas hash soportan un rastreo de  datos de tiempo constante, lo que significa que el tiempo que se toma en buscar un elemento en la tabla hash permanecerá estable, incluso si el número de entradas en la tabla se incrementa.
Para trabajar con tablas hash, CL proporciona la función constructora make-hash-table y la función de acceso gethash. Para establecer entradas en una tabla hash se usa el operador setf en conjunción con la función de acceso gethash. setf es una generalización de setq que puede usarse en sitios resultantes de una llamada a función, además de exclusivamente con símbolos como con setq. Este es un ejemplo de creación de una tabla hash, que pone un valor en ella y que recupera un valor de ella:

   > (setq so-clasif (make-hash-table))
   #S(HASH-TABLE :TEST FASTHASH-EQL)

   > (setf (gethash :windows so-clasif) "sin comentarios")
     "sin comentarios"
    
   > (gethash :windows so-clasif)
     "sin comentarios" ;
     T


Observe que la función gethash devuelve dos valores. El primer valor de retorno es el valor correspondiente a la entrada encontrada en la tabla hash, si existiera. El segundo valor de retorno es un valor booleano (T o NIL), que indica si el valor se se encontró de hecho en la tabla hash. Si el valor no se encuentra, el primer valor de retorno será NIL y el segundo será también NIL. Este segundo valor es necesario para distinguir los casos en los que la entrada sí se encuentra en la tabla hash, pero sucede que su valor es precisamente NIL. Existen varias vías para acceder a múltiples valores de retorno de una función, empleando multiple-value-bind y multiple-value-list.

En proximas entregas veremos como trabajar con tablas hash, eliminar registros, guardarla en un archivo, etc.
Mi mujer me dijo que si no llevo dinero a casa, me echa y que va a salir con el carnicero de la esquina. :-(

domingo, 15 de julio de 2012

Listas (cuarta parte): Diversas funciones utiles


¿Es una Lista...?

 Para saber si un objeto es una lista o no, usamos la función Listp. Los valores devueltos pueden ser T (verdadero) o nil (falso).

 > (setq una-lista '("hola" "estoy a 200 km de casa" "vacaciones"))
("hola" "estoy a 200 km de casa" "vacaciones")

> (listp una-lista)
T

> (setq valor 38)
38

> (listp valor)
NIL

> (setq valor "grados")
"grados"

> (listp valor)
NIL

Lista vacía

La función null nos dirá si una lista esta vacía, es decir, que no tiene elementos. null devuelte T si la lista está vacía, caso contrario devuelte NIL. 

> (set 'lista '("hola" "como" "estas")
("hola" "como" "estas")

> (null lista)
NIL

> (set 'lista nil)
NIL

> (null lista)
T

Longitud de una lista


La longitud de una lista se obtiene con la función length:

> (setq una-lista '("uno" "dos" 3 "cuatro" 5.0 6e00))
("uno" "dos" 3 "cuatro" 5.0 6.0)

> (length una-lista)
6

Obtención de parte de una lista

subseq es una función común que se usa para devolver parte de una lista. Toma al menos dos argumentos, una lista y un entero que indica la posición desde donde empezar. También toma un tercer argumento optativo, un entero que indica la posición donde detenerse. Observe que la posición indicada por este tercer argumento no se incluye en el la sub-lista devuelta:

> (setq una-lista '("uno" "dos" "tres" "cuatro" "cinco"))
("uno" "dos" "tres" "cuatro" "cinco")

> (setq otra-lista (subseq una-lista 1 3))
("dos" "tres")

> (setq otra-lista (subseq una-lista 0 2))
("uno" "dos")

> (setq otra-lista (subseq una-lista 1))
("dos" "tres" "cuatro" "cinco")

Unir varias listas en una sola


Las listas se pueden unir con append:

> (setq lista-uno '(1 2 3 4 5 6))
(1 2 3 4 5 6)

> (setq lista-dos '("esto" "es" "una" "lista"))
("esto" "es" "una" "lista")

> (setq lista-tres '("Maria" "te" "amo"))
("Maria" "te" "amo")

> (setq lista-unica (append lista-uno lista-dos lista-tres))
(1 2 3 4 5 6 "esto" "es" "una" "lista" "Maria" "te" "amo")

Ordenar listas


Las listas se ordenan con sort:

> (setq lista-valores '(23 15 33 789 3 102 18))
(23 15 33 789 3 102 18)

> (sort lista-valores #'<)
(3 15 18 23 33 102 789)

> (sort lista-valores #'>)
(789 102 33 23 18 15 3)

El resto de una lista

La función rest devuelve la misma lista pero sin el primer elemento, es decir, devolverá el resto de la lista, luego de extraer el primer elemento. Su valor deberá ser almacenado debido a que rest es no destructiva:

> (set 'primos '(2 3 5 7 11 13 17 19 23))
(2 3 5 7 11 13 17 19 23)

> (set 'resto (rest primos))
(3 5 7 11 13 17 19 23)

Listas (tercera parte): Remover y Agregar elementos


Para remover elementos de una lista se usa la función remove:

> (setq una-lista '(15 33 "edad" 7/8))
(15 33 "hoy es domingo" 7/8)

 > una-lista
(15 33 "hoy es domingo" 7/8)

>  (remove 33 una-lista)
(15 "hoy es domingo" 7/8)

Se ha removido 33 de la lista. Sin embargo la función remove es no destructiva, por lo que no se ha modificado una-lista.

> una-lista
(15 33 "hoy es domingo" 7/8)


Por lo tanto deberíamos guardar la lista devuelta por la función:

> (setq una-lista (remove 33 una-lista))
(15 "hoy es domingo" 7/8)

> una-lista
(15 "hoy es domingo" 7/8)

Para agregar elementos se puede usar la función cons:

> (setq una-lista (cons "mañana es lunes..." una-lista))
("mañana es lunes..." 15 "hoy es domingo" 7/8)

> una-lista
("mañana es lunes..." 15 "hoy es domingo" 7/8)

Otra manera de agregar elementos es usando push. Una lista se puede tratar como una estructura de pila LIFO. Antes de poner cualquier valor, la lista debe tener algún elemento o estar vacía (tener el valor nil). 

Primero me aseguro de crear una lista vacía:

> (setf una-lista nil) 
NIL

> (push "hola" una-lista)
("hola")

> (push 23 una-lista)
(23 "hola")

> (push () una-lista)
(NIL 23 "hola")

> (push "te amo Maria" una-lista)
("te amo Maria" NIL 23 "hola")

> (push 8.5 una-lista)
(8.5 "te amo Maria" NIL 23 "hola")

Para sacar usamos pop:

> (pop una-lista)
8.5

Pero los valores que quitamos se perderían de no ser asignados:

> (setq hermosa (pop una-lista))
"te amo Maria"

> hermosa
"te amo Maria"

Listas (segunda parte) Acceder a los elementos de una lista


Para acceder al primer elemento se usa first:

> (setq una-lista '("uno" "dos" "tres" "cuatro" "cinco"))
("uno" "dos" "tres" "cuatro" "cinco")

> (setq cadena (first una-lista))
"uno"

Accede al primer elemento de la lista una-lista y guarda el valor devuelto en el simbolo cadena.

> cadena
"uno"

Para acceder al segundo y al tercero, second y third, respectivamente:

> (setq cadena (second una-lista))
"dos"

> (setq cadena (third una-lista))
"tres"

Para obtener cualquier elemento de una lista, se puede usar nth:

> (setq cadena (nth 4 una-lista))
"cinco"

> (setq cadena (nth 0 una-lista))
"uno"

> (setq cadena (nth 2 una-lista))
"tres"

Al primer elemento se accede con 0 al segundo con 1, y asi sucesivamente.

Para acceder al ultimo elemento de una lista se puede usar last:

> (setq cadena (last una-lista))
"cinco"




viernes, 15 de junio de 2012

Tipos de datos en Lisp


Tipos de datos en Lisp:

En Lisp tenemos: números, cadenas de caracteres, listas, símbolos y funciones.

CADENAS DE CARACTERES
Las cadenas de caracteres van entre comillas, como en otros lenguajes:

> “esto es una cadena”
“esto es una cadena”

SIMBOLOS
Los símbolos son espacios de memoria que pueden contener valores tal como lo hacen las variables en otros lenguajes. Sin embargo, aquí un símbolo es algo mas que lo que llamamos variable en otros lenguajes, así como ellas tiene un nombre que es una cadena de caracteres, y puede tener un valor asociado que puede ser un numero, una cadena o una lista. Pero además del espacio de valor, posee otros dos espacios: un espacio de función, y un espacio de lista de propiedades o plist.


Una de las manera de asignar un valor a un símbolo es usando setq:

> (setq x “Hola”)
“Hola”
> (setq y 45)
45

El intérprete siempre evalúa lo que pongamos en el prompt. Si colocamos el símbolo, evaluará y devolverá su valor.

> x
“Hola”

> y
45

Si colocamos cualquier valor, devolverá el valor mismo.

> “Gato”
“Gato”

Si colocamos una función devolverá el resultado luego de evaluarla:

> (cuadrado 3)
9

Para desactivar la evaluación usamos la función quote y nos devolverá el símbolo mismo:

> (quote x)
X

Para simplificar el uso de quote se usa la comilla simple:

> 'x
X

> 'y
Y

LISTAS
Las listas pueden contener números, cadenas, símbolos, funciones y otras listas. Una de las maneras de hacer una lista es desactivando la evaluación:

> '(1 4 56)
(1 4 56)

Pues de lo contrario evaluará a la lista, tomándola como una función:

> (1 4 56)
*** - EVAL: 1 is not a function name; try using a symbol instead

El intérprete intenta tomar a 1 como nombre de una función y el resto serían sus argumentos. Como no se pueden usar números como nombres de función devuelve error.

Otro ejemplo:
> '(cuadrado 4)
(CUADRADO 4)

Como la evaluación está desactivada, el intérprete devuelve la lista formada por el símbolo cuadrado y el número 4. Con la evaluación activa:

> (cuadrado 4)
16

Evalúa la función cuadrado y devuelve el resultado correspondiente.

Otro ejemplo de lista y van...
> '(2.32 -7 4E-5 #C(1 -1) “esta lista es copada” (1 2 3 a) b)
(2.32 -7 “esta lista es copada” (1 2 3 A) B)


NUMEROS
Los números pueden ser enteros, decimales, de coma flotante, fracciones o complejos.

Tipos
Ejemplos
Enteros
> -3
-3
> 5
5
Decimales
> 7.8
7.8
> 3.14159265
3.14159265
Notación Científica
> 4.46E4
44600.0

> 1.65E6
1650000.0
> 7.9E-12
7.9E-12

> 8.2E32
8.2E32
Fracciones
> 2/3
2/3
> -5/8
-5/8
Complejos
El primer valor corresponde a la parte real, el segundo a la imaginaria.
> #C(2 3)
#C(2 3)


> #C(-1 5)
#C(-1 5)

Algunas Operaciones Aritméticas

Operación Aritmética
Ejemplos
Suma
> (+ 1 2)
> 3

> (+ 3.2 7)
10.2
> (+ 3/2 1/5)
17/10

> (+ #C(2 3) #C(1 -5))
#C(3 -2)
Resta
> (- 6 9)
-3
> (- #C(1 1) #C(2 3))
#C(-1 -2)
Multiplicación
> (* 3 4)
12
> (* 2 3 7)
42
División
> (/ 4 -2)
-2
> (/ 15 6)
5/2
Potencia
> (expt 2 3)
8

> (expt 7/8 5)
16807/32768
> (expt #C(4 -1) -2)
#C(15/289 8/289)
Raíz cuadrada
> (sqrt 16)
4


PD: Aquí tengo el libro de Cooper traducido al español:
Técnicas Básicas de Lisp - David Cooper.pdf