miércoles, 7 de octubre de 2009

La ciencia en España no necesita tijeras



Hola a todos:

Como ya sabréis, los presupuestos españoles para el año 2010 contemplan una reducción muy importante del dinero destinado a la ciencia en España. Desde este humilde blog quiero unirme a la campaña lanzada por la aldea irreductible en contra de esta reducción de fondos.

lunes, 26 de enero de 2009

Primeros pasos con LTK (parte 4)

Hola de nuevo:

Hoy vamos a hablar sobre cómo hacer que nuestras aplicaciones en LTK respondan a estímulos del mundo exterior. Exacto! Vamos a hablar de la gestión de eventos.

Aquellos que no hayáis programado nunca una aplicación gráfica seguramente os estáis preguntando qué es esto de los eventos. Bien. Una aplicación gráfica normalmente no está haciendo cosas todo el tiempo, sino que se espera a que pase algo y en ese momento responde. Por ejemplo, al hacer click en el botón "actualizar", firefox actualizará la página web que estáis viendo en este momento. Antes de pulsar el botón, firefox no está haciendo nada. Cuando pulsáis el botón, la librería gráfica le dice a firefox "oye, que el chaval este ha pulsao un botón, haz algo" y firefox responde desperezándose y renovando la página. Ese algo que ha provocado la reacción del programa ( en nuestro caso, la pulsación de un botón ) se llama evento. Podríamos decir que un esquema bastante general de una aplicación gráfica sería el siguiente:
  1. La aplicación arranca.
  2. La aplicación se queda esperando que suceda un evento.
  3. Sucede un evento. La aplicación actúa según qué evento sea.
  4. Una vez finalizada la respuesta al evento, la aplicación vuelve a esperar que suceda un nuevo evento.
  5. ...
  6. Sucede algo que hace que la aplicación decida terminar.
Hoy aprenderemos a gestionar algunos eventos básicos en nuestras aplicaciones.

La función bind

La manera que tiene LTK de gestionar eventos es particularmente simple. Lo que hacemos es vincular un evento con un determinado widget y una función, de manera que cuando ese evento le suceda a ese widget será esa la función que se ejecute. En algunos toolkits gráficos lo que se envía es un evento junto con el widget que lo ha provocado y nos las tenemos que apañar para decidir cómo actuar. Afortunadamente, en LTK esto no es así ( como en la mayoría de toolkits gráficos actuales, tendría que añadir. Aquellos malos tiempos ya pasaron, a no ser que queráis hacer algo de muy bajo nivel ).

La manera de hacer lo que hemos dicho es mediante la función bind. Su formato es el siguiente:

(bind widget nombreEvento FuncionAEjecutar )

Por ejemplo, vamos a hacer que al hacer click sobre una etiqueta se ejecute una función, de forma que imitaremos un botón. Sí, bueno, ya tenemos botones, pero recordad que estamos aprendiendo, así que empezaremos por algo sencillo.

NOTA: los nombres de los eventos se deben cerrar entre <>. Por alguna extraña razón, blogger no me deja.

Un trozo de código lisp que nos crearía la interfaz sería


(use-package :ltk )


(with-ltk ()
(let
(
(etiqueta (make-instance 'label :master nil :text "Etiqueta" ))
)
(pack etiqueta )
)
)

Ahora simplemente vamos a añadir una línea para que la etiqueta muestre por pantalla "Hola" cuando le hagamos click encima. Esta línea sería la siguiente:

(bind etiqueta "Button-1" (lambda (x) (print 'hola )))

Los eventos en LTK se nombran mediante cadenas de texto. Por ejemplo, "" identifica la pulsación del botón izquierdo del ratón. Hay muchos otros eventos, y además se admiten abreviaciones. La función que asignamos necesita un argumento porque se le pasa un objeto de tipo evento que en este ejemplo no necesitamos usar. Nuestro código final sería, pues:

(use-package :ltk )


(with-ltk ()
(let
(
(etiqueta (make-instance 'label :master nil :text "Etiqueta" ))
)
(bind etiqueta "Button-1" (lambda (x) (print 'hola )))
(pack etiqueta )
)
)

Podemos ver el resultado de pulsar 3 veces encima de la etiqueta:

Ahora pasaremos a ver cómo conseguir que los widgets cambien de color en cuanto les pasamos el ratón por encima. Así podemos consiguir efectos muy bonitos si elegimos los colores con gusto. Hay otras formas más sencillas de hacerlo, pero nos vamos a olvidar de ellas. Probad el siguiente ejemplo:

(with-ltk ()
(let
(
(etiqueta (make-instance 'label :master nil :text "Etiqueta" :background "gray" ))
)
(bind etiqueta "Enter" (lambda (x) (configure etiqueta :background "green" )))
(bind etiqueta "Leave" (lambda (x) (configure etiqueta :background "gray" )))
(pack etiqueta )
)
)

Es sencillo entenderlo. Simplemente creamos una etiqueta con el fondo gris, usando la opción background. Entonces le asociamos dos eventos:
  1. Cuando el ratón entre al widget, reconfiguramos la etiqueta para que tenga el fondo verde.
  2. Cuando el ratón se retire de la etiqueta, la reconfiguramos para que vuelva a tener el fondo gris.
De esta forma conseguimos el efecto de destacar la etiqueta. Desgraciadamente no tengo buen gusto para los colores :-)


Os dejo un enlace a un tutorial de la Universidad de Oviedo dónde podéis encontrar una lista con algunos eventos y algo más de información sobre ellos:

http://www6.uniovi.es/tcl/tutorial/cap12.html

Por hoy ya tenemos suficiente.

He de pediros disculpas por no haber escrito nada durante mucho tiempo. He tenido que examinarme del máster y no he podido hacer nada más, pero espero poder escribir más a menudo a partir de ahora.

Nos vemos!

PD: me gustaría programar un pequeño juego en ltk como programa final, para cuando haya acabado el curso. Si queréis proponerme algo, escribidlo como comentario en esta entrada. Yo había pensando en un tres en ralla, un buscaminas o algo similar. Pensad que debe ser algo que se pueda explicar en un máximo de 2 o 3 posts. Agradeceré vuestras sugerencias.

sábado, 20 de diciembre de 2008

Scripting en lisp

Hola:

Quería escribir esta entrada para comentar algo que me ha sucedido recientemente y que viene al caso de la utilidad de lisp para escribir scripts para la administración de sistemas, al estilo de lo que se suele hacer en perl.

Veamos la situación: recientemente me compré un Acer Aspire One ZG5 con Linux Linpus preinstalado. Por circunstancias que no vienen al caso tuve que cambiar el sistema operativo para poner Debian el Pc. Pues bien, el problema fue que quise instalar un entorno gráfico ligero ( WindowMaker ) en el cuál pretendía usar wicd para configurar mi red inalámbrica. Para mi sorpresa, wicd no funcionó. Lejos de suponer un problema, configuré la red editando manualmente el archivo /etc/network/interfaces y obtuve conexión a internet. Esto sucedió en el trabajo.

Al llegar a mi casa, más de lo mismo. Wicd no conectaba a mi red wireless y tuve que crear un nuevo archivo de configuración para mi red casera. Resumiendo: la situación era la siguiente: 2 archivos de configuración (/etc/network/interfaces.wep y /etc/network/interfaces.wpa ) y un enlace simbólico al archivo correcto que debía crear manualmente cada vez que quería cambiar de red, además de llamar al dichoso /etc/init.d/networking restart cada vez, para conectar.

Aunque no es algo excesivamente tedioso, enseguida pensé en escribir un script que automatizara el proceso de conectar a la red que quisiera, y se me ocurrió escribirlo en lisp en lugar de hacer el típico shell script. La idea era crear un pequeño programa que borrara el enlace existente, substituyéndolo por un nuevo enlace al archivo de configuración correcto y luego llamara a /etc/init.d/networking restart para conectarme a la red. No parecía difícil hacerlo en lisp, pues.

Para ejecutar procesos del linux desde lisp necesitamos la función (escribí esto para sbcl, no debería ser difícil reescribirlo para cualquier otro lisp) (sb-ext:run-program programa lista_de_argumentos ) . Si queremos llamar a la función sin argumentos, simplemente usaremos como segundo parámetro la lista vacía (nil).

Ahora nuestro programa debería ser como sigue:

Función activar_conexion
Parámetros: nombre de la conexion a activar

Ejecuta rm -f /etc/network/interfaces
Ejecuta ln -s /etc/network/nombre_archivo_configuracion /etc/network/interfaces
Ejecuta /etc/init.d/networking restart

El resto del programa debía consistir en algo de código para guardar los nombres de los archivos de configuración. Ahí se me ocurrió la idea de hacer un programa gráfico que usara ltk. Me mostraría todos los archivos de configuración de que dispongo y yo sólo tendría que clickear en un botón para activar la conexión a internet.

Finalmente, decidí que mantendría una tabla hash llamada *conexiones* con entradas del tipo ( nombre fichero_configuracion ) dónde guardaría las conexiones de que dispongo, y que el procedimiento anadir-conexion me serviría para añadir entradas a la hash. Una vez hecho click en el botón correspondiente la función activar-conexion me activaría la conexión a internet haciendo lo que hemos dicho antes.

Pues bien, aquí tenéis el código fuente:

(require :ltk )
(use-package :ltk )

(defvar *directorio-base* "/etc/network/" )
(defvar *nombre-link* "/etc/network/interfaces" )
(defvar *conexiones* (make-hash-table :test 'equal ))

(defun anadir-nueva-conexion ( nombre nombre_arxivo )
(setf (gethash nombre *conexiones* ) nom_arxivo )
)

(defun activar-conexion ( nombre )
(if (gethash nombre *conexiones* )
(progn
(let
(
(nombre_arxivo (concatenate 'string *directorio-base* (gethash nombre *conexiones* )))
)
(print nombre_arxivo )
(sb-ext:run-program "/bin/rm" (list "-f" *nombre-link* ))
(sb-ext:run-program "/bin/ln" (list "-s" nombre_arxivo *nombre-link* ))
(sb-ext:run-program "/etc/init.d/networking" (list "restart" ))
)
)
)
)

(anadir-nueva-conexion "Eduroam UV" "interfaces.wpa" )
(anadir-nueva-conexion "Red casa" "interfaces.wep" )

(defun main ()
(setq *wish-args* (list "-name" "NetworkSwitcher" ))
(with-ltk ()
(let*
(
(marco (make-instance 'frame :master nil ))
etiqueta
)
(maphash (lambda (key value )
(declare (ignore value ))
(setq etiqueta (make-instance 'button :master marc :width 12 :text key
:command (lambda ()
(print key )
(activar-conexion key ))
))
(pack etiqueta )
)
*conexiones* )
(pack marco )
)
)
)


(main)

Al arrancar el programa se ven 2 botones, uno con la etiqueta "Red casa" y otro con la etiqueta "Eduroam UV". Al hacerles click activo la red correspondiente.

Sencillo, no? Mucha gente pensará que debería leerme la faq de wicd en lugar de perder el tiempo en estas cosas, pero realmente he aprendido y disfrutado haciéndolo, así que me doy por satisfecho.

Adiós!!! Felices fiestas a todos!!

jueves, 27 de noviembre de 2008

Primeros pasos con LTK (parte 3)

A vueltas con el pack

Hoy vamos aprender a colocar nuestros widgets en la pantalla. Quizás no sea un tema muy atractivo, pero sí es absolutamente necesario, así que pongámonos manos a la obra.

Vamos a empezar por crear unas cuantas etiquetas que iremos posicionando de distintas maneras.

(let
(
(marco (make-instance 'frame :master nil ))
(etiqueta1 (make-instance 'label :master marco :text "Etiqueta 1"))
(etiqueta2 (make-instance 'label :master marco :text "Etiqueta 2" ))
(etiqueta3 (make-instance 'label :master marco :text "Etiqueta 3" ))
(etiqueta4 (make-instance 'label :master marco :text "Etiqueta 4" ))
)
)


El código de arriba nos crea las etiquetas pero no se ocupa de posicionarlas en la pantalla. Es ahora cuando entra en juego el pack. Empecemos por ver cómo las posiciona por defecto:

(with-ltk ()
(let*

(
(marco (make-instance 'frame :master nil ))

(etiqueta1 (make-instance 'label :master marco :text "Etiqueta 1"))
(etiqueta2 (make-instance 'label :master marco :text "Etiqueta 2" ))
(etiqueta3 (make-instance 'label :master marco :text "Etiqueta 3" ))
(etiqueta4 (make-instance 'label :master marco :text "Etiqueta 4" ))

)
(pack marco)
(pack etiqueta1 )
(pack etiqueta2 )
(pack etiqueta3 )
(pack etiqueta4 )
)
)

Por defecto, pack coloca los widgets de arriba a abajo. El resultado del código anterior es lo siguiente:


Es importante darse cuenta de que LTK no muestra los widgets en el orden en que fueron creados, sino en el orden en que se llama a pack. En el ejemplo anterior, ha puesto arriba a etiqueta1 porque ha sido la primera con la que hemos llamado a pack, pero podríamos hacerlo de cualquier otra manera:





(let*
(
(marco (make-instance 'frame :master nil ))
(etiqueta1 (make-instance 'label :master marco :text "Etiqueta 1"))
(etiqueta2 (make-instance 'label :master marco :text "Etiqueta 2" ))
(etiqueta3 (make-instance 'label :master marco :text "Etiqueta 3" ))
(etiqueta4 (make-instance 'label :master marco :text "Etiqueta 4" ))
)
(pack marco)
(pack etiqueta4 )
(pack etiqueta2 )
(pack etiqueta1 )
(pack etiqueta3 )
)
y el resultado sería que los widgets se muestran en otro orden, que no tiene nada que ver con el orden en el que fueron creados:


Ahora vamos a situar los widgets lateralmente. Para ello sólo debemos hacer uso de la opción :side del pack. Veamos un ejemplo:

(with-ltk ()
(let*
(
(marco (make-instance 'frame :master nil ))
(etiqueta1 (make-instance 'label :master marco :text "Etiqueta 1"))

(etiqueta2 (make-instance 'label :master marco :text "Etiqueta 2" ))
(etiqueta3 (make-instance 'label :master marco :text "Etiqueta 3" ))
(etiqueta4 (make-instance 'label :master marco :text "Etiqueta 4" ))
)

(pack marco)
(pack etiqueta1 :side :left)
(pack etiqueta2 :side :left)
(pack etiqueta3 :side :left)
(pack etiqueta4 :side :left)
)
)

El resultado es que los widgets se situan de izquierda a derecha:

También podemos situarlos de derecha a izquierda usando :side :right:

(with-ltk ()
(let*

(
(marco (make-instance 'frame :master nil ))
(etiqueta1 (make-instance 'label :master marco :text "Etiqueta 1"))
(etiqueta2 (make-instance 'label :master marco :text "Etiqueta 2" ))
(etiqueta3 (make-instance 'label :master marco :text "Etiqueta 3" ))
(etiqueta4 (make-instance 'label :master marco :text "Etiqueta 4" ))
)
(pack marco)
(pack etiqueta1 :side :right)
(pack etiqueta2 :side :right)
(pack etiqueta3 :side :right)
(pack etiqueta4 :side :right)
)
)

Fijáos cómo la etiqueta1 ahora está a la derecha:


Por último, veremos cómo poner las etiquetas de abajo a arriba. Esto no suele ser muy útil porque es lo mismo que ponerlas de arriba a abajo llamando a pack en orden inverso, pero lo pongo por completitud. Se hace justo como suponéis, usando :side :bottom:
(with-ltk ()
(let*

(

(marco (make-instance 'frame :master nil ))
(etiqueta1 (make-instance 'label :master marco :text "Etiqueta 1"))
(etiqueta2 (make-instance 'label :master marco :text "Etiqueta 2" ))
(etiqueta3 (make-instance 'label :master marco :text "Etiqueta 3" ))
(etiqueta4 (make-instance 'label :master marco :text "Etiqueta 4" ))
)
(pack marco)
(pack etiqueta1 :side :bottom)
(pack etiqueta2 :side :bottom)
(pack etiqueta3 :side :bottom)
(pack etiqueta4 :side :bottom)
)
)
Esto es todo lo que veremos hoy sobre pack. Con lo que ya sabéis podéis crear interfaces complicadas. ¿Cómo? Solamente habéis de crear marcos y meter los widgets en ellos en el orden adecuado. En el capítulo sobre el widget frame veremos como hacer esto.

El grid

Aunque en principio no pensaba tratarlo, voy a hablar un poco sobre grid. Es un geometry manager distinto a pack. No deben mezclarse pack y grid en el mismo marco porque podemos crear un pequeño desastre con la colocación de los widgets. De todas formas, grid es útil porque lo que hace es situar los widgets en una cuadrícula, de forma que nos simplifica la vida en aplicaciones tipo hojas de cálculo y similares. Su sintaxis básica es muy sencilla:

(grid widget fila columna)

Fila y columna son enteros, representan el número de fila y columna (lógico). La primera fila es la 0, al igual que la primera columna. Veamos cómo situar nuestras 4 etiquetas en una rejilla 2x2:

(with-ltk ()
(let*

(
(marco (make-instance 'frame :master nil ))
(etiqueta1 (make-instance 'label :master marco :text "Etiqueta 1" ))
(etiqueta2 (make-instance 'label :master marco :text "Etiqueta 2" ))
(etiqueta3 (make-instance 'label :master marco :text "Etiqueta 3" ))
(etiqueta4 (make-instance 'label :master marco :text "Etiqueta 4" ))
)
(pack marco)
(grid etiqueta1 0 0)
(grid etiqueta2 0 1)

(grid etiqueta3 1 0)
(grid etiqueta4 1 1)
)
)

El resultado es el esperado:



Para finalizar os voy a enseñar un pequeño truco. Si os fijáis en el ejemplo anterior, no se distinguen unas etiquetas de las otras. Eso es porque no tienen relieve. Pues bien, vamos a añadirlo! Todo widget tiene una opción llamada :relief que puede tomar varios valores. Os pongo un código de ejemplo y tratad de averiguar que hace:
(with-ltk ()
(let*
(
(marco (make-instance 'frame :master nil ))

(etiqueta1 (make-instance 'label :master marco :text "Etiqueta 1" :relief :sunken))
(etiqueta2 (make-instance 'label :master marco :text "Etiqueta 2" :relief :sunken))
(etiqueta3 (make-instance 'label :master marco :text "Etiqueta 3" :relief :sunken))
(etiqueta4 (make-instance 'label :master marco :text "Etiqueta 4" :relief :sunken))
)
(pack marco)
(grid etiqueta1 0 0)
(grid etiqueta2 0 1)
(grid etiqueta3 1 0)
(grid etiqueta4 1 1)
)
)

Hemos hundido las etiquetas, de forma que la separación entre ellas queda visible. Se pueden hacer cosas más bonitas :-)

Nos vemos en el próximo post!

miércoles, 5 de noviembre de 2008

Primeros pasos con LTK (parte 2)

Hola!

Hoy vamos a seguir con la introducción a LTK que iniciamos hace unos días.

Empezaremos por comentar el ejemplo que ya vimos y que nos mostraba "Hola, mundo" en una etiqueta:

(use-package :ltk )
(with-ltk ()
(let
(
( etiqueta (make-instance 'label :master nil :text "Hola, mundo" ))
)
(pack etiqueta)
)
)

Bien. La primera línea es conocida: (use-package :ltk) simplemente importa los símbolos que necesitamos, para no tener que escribir todo el rato ltk:laFuncionQueNosInteresa.

Es en la segunda línea donde empezamos a usar ltk. La macro with-ltk inicializa la librería y ejecuta todo el código que metemos en su cuerpo. Tiene unos parámetros opcionales ( en nuestro caso, la lista vacía --()-- ) que nos permiten controlar ciertas opciones de debug.

Cada tipo de widget en ltk se representa mediante una clase. Por eso, cuando llamamos a make-instance 'label estamos creando una etiqueta. Todos los widgets de ltk tienen unas opciones de inicialización comunes:
  • master : el widget padre. Si lo dejamos a nil, ltk tomará a este widget como del nivel padre
Pack es lo que se llama un "package manager", o gestor de empaquetado. Es la función que usamos cuando queremos situar un widget sobre la pantalla, y se encarga de tareas como su posición relativa a otros widgets y (en ocasiones) su tamaño. Existen varios package managers, pero pack es el más utilizado, así que será el que comentaremos aquí. Si queréis saber más sobre el resto de managers, una forma fácil de empezar es man grid o man place.

Cuando trabajamos con pack lo que hacemos es situar los widgets en cajas. Podemos elegir si situaremos estas cajas de arriba a abajo ( por defecto en pack ), de abajo a arriba, de izquierda a derecha o de derecha a izquierda. También nos permite elegir si queremos que el widget se vea elevado sobre la caja, hundido o de diversas formas.

El widget label ( la etiqueta )

El widget label es uno de los más básicos y sencillos de utilizar. Simplemente es una etiqueta donde podemos mostrar texto.

La forma más común de crear un label es mediante

(make-instance 'label :master suPadre :text "SuTexto" )

Esto ajustará automáticamente el tamaño de la etiqueta al del texto que contiene.

A veces resulta muy conveniente, a fin de realizar interfaces más bonitas, controlar el ancho de las etiquetas para que todas tengan el mismo tamaño. Esto se hace mediante la opción de inicialización :width suAncho , dónde suAncho es un entero. El ancho de un label se mide en carácteres, por tanto :width 10 significará que queremos una etiqueta con un ancho de 10 carácteres.

Evidentemente, hay muchas más opciones interesantes para los label. man label para verlas.

El widget button ( el botón )

El widget button ofrece lo que promete: un botón. Su inicialización es muy similar a la del widget label, excepto por el hecho de que nos deja proporcionarle un argumento command que es la función que ejecutará cuando sea pulsado.

(make-instance 'button :master nil :text "Pulsame"
:command ( lambda ()
(format t "Has pulsado el boton~%" )
)

A ver si imagináis que hace el código anterior.

miércoles, 15 de octubre de 2008

Dibujando gráficas en 2 patadas con CGN

Hola:

Sí, el título podía ser más formal, pero hoy nos interesa ir deprisa...

Vamos a aprender a dibujar gráficas en Gnuplot desde lisp. Gnuplot es un conocido programa para dibujar gráficas de funciones y puntos (las últimas versiones hacen más cosas, como por ejemplo histogramas) que seguramente ya conoceréis. Así que manos a la obra!

Existen muchas alternativas en lo que a controlar gnuplot desde lisp se refiere. En cliki podéis encontrarlas. Aquí me limitaré a enseñaros a dibujar con CGN. ¿ Por qué CGN? Pues porque soy su autor, así que es la librería que mejor conozco y la que suelo usar, aunque no la mejor. Os invito a que probéis el resto y me contéis cómo ha sido la experiencia. Podemos publicarlo en este blog para ayudar a más gente.

¿Cómo instalaremos CGN? Pues de la manera que os imagináis: 

(asdf-install:install 'cgn )

CGN depende de la librería gráfica LTK, así que asdf-install la instalará por vosotros. Ahora bien, para este tutorial os recomiendo usar la versión que se halla en el repositorio darcs,  que se debe instalar a mano. La función plot2d que usaremos aquí sólo se encuentra en esa versión. Lo siento, todavía no he lanzado una release actualizada.

Dibujando con plot2d:

Para empezar a dibujar con CGN sólo hay que saber usar 2 cosas: la macro with-gnuplot y la función plot2d. 

Empecemos por la macro: para dibujar con CGN hay que escribir el código dentro de la macro 

(with-gnuplot () 

;;Código aquí

)

No nos interesa ahora lo que podemos ponerle como argumento. ¡Queremos empezar a dibujar, ya! Pues bien: aquí está lo más sencillo y útil que le podemos poner como argumento: plot2d.

Plot2d es una función que pretende ofrecer la funcionalidad que proporciona el comando del mismo nombre en Maxima.  Su sintaxis básica es :

(plot2d quePlotear rangoX &rest opciones )

rangoX ha de ser una lista con el formato ( 'x xminimo xmaximo ). quePlotear puede ser muchas cosas: un string ( "sin(x)" ) , una función ( #'cos ) , una lambda function, una lista de puntos o una lista conteniendo todo lo anterior. De las opciones no hablaremos de momento, hay prisa!

Por ejemplo, mostramos el seno:

(with-gnuplot () 
  (cgn::plot2d "sin(x)" '(x 0 10 ) ) )















Si le pasamos una función, CGN la dibujará en los puntos que crea necesario:

(with-gnuplot ()
  (cgn::plot2d #'cos '(x 0 10 ) ) )
















Otra opción es hacer un gráfico de puntos:

(with-gnuplot ()
  (cgn::plot2d '(discrete (1 2 3 4 5 6 7 8 9 10 ) (1.1 2.5 4.21 2.12 3.15 4.57 6.87 8.74 12.5 13.4789 ) ) '(x 0 10 ) ) 
)

















Podéis ver una muestra de lo que plot2d puede hacer ejecutando (cgn::plot2d-test). En el manual en pdf que se incluye en la versión de desarrollo se explica todo.

La forma rápida y simple

Existe una forma para que hasta un niño pueda hacer gráficas en CGN. Consiste en usar  el easy-plotter. Easy-plotter es una interfaz gráfica escrita en ltk para la macro plot (sí, esto también es una novedad de la versión del repositorio) que nos permite escribir simplemente la función que usaremos y plotearla. Lamentablemente, no sirve para plotear funciones de lisp ni lambda functions, pero es muy sencilla de usar:

(cgn::easy-plotter)



Parece sencillo, ¿verdad? Probadlo. CGN puede hacer muchas más cosas, pero me tengo que ir a clase, así que no hay tiempo para contarlas. Espero que esto os haya resultado útil. Ah! Por favor, la versión del repositorio está todavía en desarrollo, así que no seáis muy crueles con los fallos que encontréis. ¡Adiós!

sábado, 4 de octubre de 2008

Bienvenidos, sobrelisp!

Desde aquí quiero dar la bienvenida a un blog hermano que ha sido creado recientemente , sobrelisp.blogspot.com.

David y yo esperamos que estos dos blogs se complementen para impulsar lisp en la comunidad hispanohablante.

Buena suerte!