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.
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
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.
Etiquetas:
.lisp,
Common Lisp,
lisp,
listas,
propiedades,
record,
registro,
registros
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:
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:
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. :-(
Etiquetas:
array,
arrays,
arreglo,
datos,
lisp,
listas,
propiedades,
tablas hash,
Tipos
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
|
|
Suscribirse a:
Entradas (Atom)


