Social Icons

domingo, 1 de mayo de 2016

Una Adecuación de Ubuntu 16.04 tras su Instalación.

Introducción

Traemos hoy a éste nuestro diario una adecuación de la instalación
de Ubuntu 16.04 cuando el propósito es usarlo en ambiente académico.

Es ya una costumbre entre nuestros lectores recibir aquí información
puesta al día sobre estas adecuaciones y hemos de decir que hay
pocas novedades respecto a la reseña dada para la
Ubuntu 14.04. Tomaremos como base ésta y añadiremos las diferencias.

Para leer el post copleto, pulse aquí.


domingo, 10 de enero de 2016

Instalar ELPA para Emacs 23

Introducción
Los usuarios de Emacs saben de su editor preferido varias cosas: la independencia que les ha proporcionado del ratón por venir de un tiempo en el que se vivía sin ratón, la sensación de control pleno que les confiere, la potencia del mismo y también la dificultad de su configuración al ir un poquitín más allá de lo elemental.

En particular es complicada la gestión de instalar complementos para Emacs. ¿Cuántas veces hemos recurrido a instalarlos mediante el gestor de paquetes del sistema operativo, lo cual es menos que ideal? El deseo de los usuarios de Emacs ha sido por largo tiempo disponer de un sistema gestor de paquetes como:aptyumhomebrewpip, etc. Emacs 24 lo ha hecho finalmente; se llama package.elELPA es el acrónimo de “Emacs Lisp Package Archive”, escrito originalmente por Tom Tromey. Está incluida enGnuEmacs a partir de la versión 24. La biblioteca del gestor de paquetes para el ELPA es package.el.

Pero ¿qué hay de Emacs 23 y las versiones anteriores? Este post está dedicado a los usuarios, puede que administradores, que están usando Emacs 23, quizá porque están apurando una versión antigua de su sistema y no pueden cambiar a Emacs 24 o quizá porque encuetran en la versión 23 algún rasgo que les interesa, etc. Explicaremos la inexplicada y sencilla labor de poner package.el a disposición de su Emacs 23

Para leer el post copleto, pulse aquí.

viernes, 11 de diciembre de 2015

Acceder a un servidor mediante ssh y un certificado

Introducción

Cuando nos es abierta una cuenta en un servidor, el administrador tiene un problema, cual es hacernos llegar la contraseña. Si la envía en abierto, estará comprometida; si la envía cifrada, ¿hasta cuando puede extenderse la labor de compartir contraseñas?

La solución a esta dificultad se basa en facilitar el acceso del usuario mediante el uso de certificados. El administrador: abrirá la cuenta, habilitará el servidor para poder acceder a las cuentas mediante certificados, notificará al usuario que su cuenta está abierta y quedará a la espera del certificado público de acceso.

Por su parte, el usuario procederá a generar una pareja de certificados: el público y el privado, le hará llegar al administrador el público en abierto y éste procederá a habilitar el acceso mediante él y el privado, que sólo conocerá el usuario y tendrá guardado celosamente incluso bajo un password dado en el momento de la generación.

De esta manera incluso podremos tener una cuenta compartida por varios usuarios, siempre que éstos consientan, de lo que será garante el administrador.

Para leer el post completo, pulse aquí.

miércoles, 9 de septiembre de 2015

Instalar IPython mediante pip en Ubuntu 14.04 y Mac OS X "El Capitan"

Introducción

Una vez que hemos decido no hacer frente a los gastos del uso legal de Mathematica y hemos desechado la ideas usar Maxima por las razones ya bien conocidas, una buena apuesta es llamar a la puerta de Python y servirse de las herramientas que se han derivado de él en la última década; nos referimos a sagemath e IPython.

A la instalación de sagemath le hemos dedicado un instructivo post en este blog. A IPython le dedicaremos alguno pronto, pero hay una dificultad en su instalación, la que a nosotros nos gusta, que urge solventar.

No conocemos mejor directriz de instalación que la dada en la página oficial donde en el apartado "I already have Python", dentro de la casuística de instalación sugiere el uso de pip (esta herramienta ha sido explicada en nuestro post titulado "Mi Primera Clase de Python"). Por supuesto que casi la totalidad del común de los usuario estará en esta situación, a saber, la de "yo ya tengo Python".

IPython en Ubuntu mediante pip

El asunto es que al ejecutar la orden de instalación recomendada en la página oficial, concretamente la orden

sudo pip install "ipython[notebook]"

fracasa la instalación de la librería pyzmq con el siguiente mensaje:
   
           error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
           ----------------------------------------
Command "/usr/bin/python3 -c "import setuptools, tokenize;__file__='/tmp/pip-build-23a2_por/pyzmq/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" fetch_libzmq install --record /tmp/pip-wmhla3sg-record/install-record.txt --single-version-externally-managed --compile --zmq=bundled" failed with error code 1 in /tmp/pip-build-23a2_por/pyzmq


Una vez analizado se ve que la razón de esta dificultad es que faltan librerías de desarrollo de Python de las provistas en los paquetes alojados en los repositorios de Ubuntu.

Es tan simple como instalar, si no estuviesen ya instalados, los  paquetes que se sugieren a continuación:

sudo apt-get install python-dev
sudo apt-get install python3-dev

y posteriormente instalar g++:

sudo apt-get install g++

Y con esto podremos ya llevar a cabo la instalación sugerida según la orden:

sudo pip install "ipython[notebook]"

Por supuesto que nada de esto sería preciso si tan solo huviéramos optado por la instalación básica de IPython:

sudo pip install ipython

Seguidamente, si queremos instalar la librería de Python llamada matplotlib necesitaremos el paquete libfreetype6-dev:

sudo apt-get install libfreetype6-dev

con lo que podremos hacer la instalación de matplotlib con pip:

sudo pip install matplotlib

Si nos faltase la librería matplotlib, al intentar instalarla con pip tendríamos al final un mensaje de error que acaba en:

    TypeError: unorderable types: str() < int()
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-6fus7qwz/matplotlib


Convendría, a nuestro entender, instalar sympy por lo que ejecutaremos:

sudo pip install sympy

Otra librería conveniente es scipy . Para ellas necesitaremos los paquetes instalados ejecutando:

sudo apt-get install libblas-dev liblapack-dev
sudo apt-get install python-dev gfortran

y ya con esto instalamos scipy:

sudo pip install scipy

Si queremos instalar pygraphviz necesitamos la librería libgraphviz-dev:

sudo apt-get install libgraphviz-dev

tras lo cual ejecutaremos:

sudo pip install pygraphviz

IPython en Mac OS X "El Capitan" mediante pip

Puede leer los detalles en la ampliación de este post.

Resumen Sin Comentarios

Hemos hecho la siguiente instalación (en algunos de los pasos deberemos tener paciencia, mucha paciencia):

sudo apt-get install python-dev

sudo apt-get install python3-dev

sudo apt-get install g++

sudo pip install "ipython[notebook]"

sudo apt-get install libfreetype6-dev

sudo pip install matplotlib

sudo pip install sympy

sudo apt-get install libblas-dev liblapack-dev

sudo apt-get install python-dev gfortran

sudo pip install scipy

sudo apt-get install libgraphviz-dev

sudo pip install pygraphviz
 




Y ... esto es todo por hoy.



sábado, 31 de enero de 2015

Instalar TeX Live en Ubuntu sin usar apt-get

Introducción

Como es bien sabido, el software que se instala en Ubuntu/Debian con apt-get es a menudo antiguo. Es el caso de la distribución de Tex Live de LaTeX al instalar Ubuntu 14.04 LTS: con apt-get se instala TeX Live 2013/Debian pudiendo bien estar viva ya la versión TeX Live 2014 u otra posterior.

En este post explicaremos como instalar la última distribución de TeX Live en nuestro Ubuntu o cualquier otro Linux. Para ello evitaremos el uso de apt-get obviamente.

Realmente la decisión de no utilizar apt-get para instalar TeX Live conlleva, como diremos, no instalar con apt-get: auctex, catdvi y sagemath.


Instalación de TeX Live

texlive es nuestra distribución preferida de LaTeX. Resulta penoso ver como con nuestra instalación de Ubuntu, si instalamos texlive con apt-get, casi siempre instalamos una versión antigua de nuestro LaTeX.

Para evitarlo podemos hacer una instalación manual de  texlive por medio de las siguientes instrucciones.  Lo primero es instalar perl-tk:

sudo apt-get install perl-tk

seguidamente, según figura en "Installing TeX Live over the Internet", podemos bajar el instalador para Unix: un pequeño programita que nos facilita la instalación.  Si se prefiere algo universal podemos  bajar este otro instalador  pero no es necesario ni recomendable en modo alguno para nuestro Ubuntu. Suponiendo  que tenemos ya "install-tl-unx.tar.gz", abrimos la consola y vamos al lugar donde se ha ubicado, supongamos para fijar ideas que es /Descargas tras lo que ejecutaremos

tar -xf install-tl-unx.tar.gz 

se habrá generado tras ello colgando de /Descargas un directorio con un nombre algo así como éste:

install-tl-20150125

entrando en ese directorio (mi_usuario es como habitualmente el nombre de nuestra cuenta en nuestro equipo)

cd /home/mi_usuario/Descargas/install-tl-20150125

(cada cual sustituirá "mi_usuario" e "install-tl-20150125" por lo que proceda en su situación) y seguidamente ejecutamos lo siguiente:

sudo ./install-tl -gui perltk

Se abrirá una ventana titulada "Install-tl" con la que se puede adecuar a voluntad las condiciones de la instalación.  Recomendamos firmemente hacer sólo un cambio, y no dejar de hacerlo: pulsar en el botón "Cambiar" del último apartado titulado "Crear enlaces simbólicos en los directorios de sistema", pulsar en el botón adjunto al epígrafe "crear enlaces simbólicos en los directorios estándar" (se pondrá rojo) de la pequeña subventanita que se abrirá y finalmente pulsar en el botón de ésta "Aceptar". Con ello mandamos crear los importantísimos enlaces simbólicos (esto se hace ya automáticamente):

ficheros ejecutables en: /usr/local/bin
páginas de manual en: /usr/local/share/man
información en: /usr/local/share/info

Antes figuraba junto al epígrafe "Crear enlaces simbólicos en los directorios de sistema" de la ventana principal la palabra "No" y ahora figura la palabra "Sí". Pulsamos tras cerciorarnos de ello el botón con la inscripción "Instalar Tex Live".  Ahora comienza un proceso de instalación que puede durar algún tiempo. Cuando acabe actualizaremos lo instalado desde la consola con las órdenes:

sudo tlmgr update --self
sudo tlmgr update --all

y periódicamente podemos, y debemos, repetir estas dos órdenes para mantener nuestro sistema actualizado. Podemos consultar el uso de tlmgr en este manual.

Instalación de emacs y auctex

Está claro que no es conveniente instalar auctex mediante apt-get, pues se llevaría a cabo una instalación paralela de LaTeX que en modo alguno conviene tener en el árbol del sistema interactuando con la instalación "manual" antes realizada.

No hay problema en instalar emacs disfrutando de la comodidad de apt-get; eso sí, instalaremos la última versión (al momento de escribir el post era la Emacs 24.3.1). Para ello:

sudo apt-get install emacs24

Una vez que tengamos instalado TeX Live y emacs, pasaremos a instalar auctex. Hay muchas formas de hacerlo, pero la que preferimos nosotros por su facilidad y efectividad es la siguiente:

*) abriremos emacs

*) M-x list-packages (por supuesto M-x significa Alt-x)

Si no queremos, o no podemos, usar el ratón:

*) llevar el cursor hasta auctex

*) Ctrl-x o (lleva a la segunda subventana que acaba de abrirse),  Ctrl-i (lleva al botón de "Install"),  Intro, seguidamente "y" para responder y finalmente intro.

Si preferimos usar el ratón:

*)  hacer clic sobre auctex
*)  hacer clic sobre el botón de "Install" en la subventana que se ha abierto
*)  hacer clic sobre el botón de "Yes"

En cualquiera de los casos, el proceso sabremos que ha acabado cuando veamos en la subventana inferior el mensaje "Installed".

Muy importante

Si somos usuarios de sagemath, no es conveniente instalarlo desde repositorio, pues ello significará una instalación paralela de LaTeX que quedará inconvenientemente superpuesta a la anteriormente hecha. La alternativa es la instalación manual, que es muy limpia y está explicada con sumo detalle  en éste nuestro post.

Por la misma razón deberemos evitar instalar catdvi.

Nexos de Interés

http://wwwae.ciemat.es/~oglez/webcms/oginfo/combinaciones_emacs.html
http://www.maths.manchester.ac.uk/~gb/emacs/installauctex.pdf
http://www.gnu.org/software/auctex/
https://www.gnu.org/software/auctex/manual/auctex.index.html
http://www.emacswiki.org/emacs/AUCTeX
http://www.blackhats.es/wordpress/?p=209
https://support.google.com/chrome/answer/157179?hl=es

Posdata 

La instalación de TeX Live aquí explicada soluciona el problema que presenta el editor Atom con los paquetes añadidos:

-) latex
-) language-latex

al intentar compilar un fichero .tex, arrojando el mensaje de error:

TypeError: Cannot read property 'outputFilePath' of undefined
at /home/miUsuario/.atom/packages/latex/lib/latex.coffee:63:24
at /home/miUsuario/.atom/packages/latex/lib/builders/latexmk.coffee:17:9
at ChildProcess.exithandler (child_process.js:752:5)
at ChildProcess.emit (events.js:110:17)
at maybeClose (child_process.js:1013:16)
at Socket. (child_process.js:1181:11)
at Socket.emit (events.js:107:17)
at Pipe.close (net.js:461:12)

y que ha sido explicado en el "issue outputFilePath #37" de GitHub sobre el editor Atom.


Y ... esto es todo por hoy.


sábado, 27 de septiembre de 2014

Mi Primera Clase de Haskell

Introducción

Hay un paradigma de programación que se denomina "programación declarativa".  Surge en contraposición a la "programación imperativa", que en sus comienzos estaba representada por lenguajes muy próximos a las peculiaridades de la propia máquina: operaciones artiméticas simples, instrucciones de acceso a la memoria, etc. Ese tipo de programas resultan a menudo crípticos, llegando a impedir su comprensión incluso a programadores entrenados, aunque en la actualidad los lenguajes imperativos han atenuado mucho este efecto.

La idea de la programación declarativa es escribir programas especificando o "declarando" un conjunto de condiciones, proposiciones, afirmaciones, restricciones, ecuaciones o transformaciones que describen sin ambigüedad el problema y contienen su solución. Dicha solución es obtenida mediante mecanismos internos de control para la inferencia de información, sin que el programador haya especificado exactamente cómo encontrarla. A la computadora se le indica qué es lo que se desea obtener, no cómo hacerlo. No existen asignaciones destructivas y las variables son utilizadas con "transparencia referencial".  En otras palabras, el resultado de evaluar una expresión compuesta depende únicamente del resultado de evaluar las subexpresiones que la componen y de nada más; no depende de la historia del programa en ejecución ni del orden de evaluación de las subexpresiones que la componen. Esta propiedad no se da en lenguajes imperativos, donde abundan los efectos colaterales por asignaciones destructivas. Veamos a Python, que no tiene la transparencia referencial, en un ejercicio de violación de la misma. Para ello consideremos el retazo de código siguiente que podríamos dar como contenido al fichero transparencia.py:

counter = 0

def incremental(n):
    global counter
    i = 0
    while i <= n:
          counter += 1
          i += 1
    print counter

incremental(5)
incremental(5)

para entender el efecto, podemos interpretarlo y ver que ofrece el siguiente diálogo:

iMac-de-f:last of the path ~ my_login$ python transparencia.py
6
12
 iMac-de-f:last of the path ~ my_login$

Es decir, dos invocaciones consecutivas de la misma función ---pero en ambientes diferentes--- han dado respuestas diferentes. Y es que las funciones en los lenguajes no funcionales, como es el caso de Python, no tienen por qué comportarse como funciones en el sentido matemático; son más bien algo así como "subrutinas".  Lo que un lenguaje funcional reclama, y consigue por serlo, es la recuperación de concepto "función" con el sentido dado por la matemática ... y la computación.

En estas páginas hemos hablado ya de un subparadigma del paradigma de programación declarativa cuando presentamos el post de Prolog: la programación lógica.  Tal paradigma está fundamentado por la Lógica de Primer Orden.

Sin embargo, los comienzos del siglo XX vieron como era alumbrada otra lógica, la llamada Lógica Combinatoria. Basándose en ella, o en una explicación suya denominada Lambda Calculus (desarrollado en la década de los 30 del siglo XX para investigar la noción de función, la aplicación de funciones y la recursión), surgió el segundo gran subparadigma de la programación declarativa: la programación funcional. Un lenguaje funcional es, a la postre, el resultado de una reelaboración del lambda calculus puro.

La programación funcional se basa en la utilización de funciones aritméticas que no manejan datos mutables o de estado. Hace uso de la aplicación de funciones en contraposición con el el paradigma de programación imperativa, que hace énfasis en los cambios de estado.  La diferencia entre una función matemática y la noción de función utilizada en la programación imperativa es que las funciones imperativas pueden tener efectos secundarios, al cambiar el valor de cálculos realizados previamente, carecen de transparencia referencial: la misma expresión sintáctica puede resultar en valores diferentes en diferentes momentos dependiendo del estado del programa en ejecución. Con código funcional, en contraste, el valor generado por una función depende exclusivamente de los argumentos alimentados a la función. Al eliminar los efectos secundarios se pude entender y predecir el comportamiento de un programa mucho más fácilmente, y esta es una de las principales motivaciones para utilizar la programación funcional.

El tercer gran subparadigma de la programación declarativa es la programación algebraica, representada por lenguajes como Maude y SQL.

En la actualidad, el lenguaje que encarna por antonomasia los cánones de la programación funcional es Haskell, un lenguaje de programación: estandarizado, multipropósito, puramente funcional, perezoso, con semánticas no estrictas y con fuerte tipificación estática. Su nombre se debe al lógico estadounidense Haskell B. Curry por la utilidad que tuvieron al respecto sus observaciones y las de su escuela.

Haskell nació cuando en 1980 se constituyó un comité cuyo objetivo era crear un lenguaje funcional que reuniese las características de los múltiples lenguajes funcionales de la época, el más notable de los cuales era Miranda,  y resolviera la confusión creada por la proliferación de los mismos.

Las características más interesantes de Haskell incluyen el soporte para tipos de datos y funciones recursivas, listas, tuplas, guardas y calce de patrones. La combinación de las mismas puede llevar en el caso de algunas funciones a una implementación casi trivial, y sin embargo ser su correspondiente versión en lenguajes imperativos extremadamente tediosas de programar.

Instalación

Al instalar Haskell en nuestro ordenador, conviene instalar la plataforma completa. En Ubuntu, cuando ésta está disponible, la instalación es trivial:

sudo apt-get install haskell-platform

y si somos felices usuarios de Mac OS X  con macport instalado (depende de Xcode y posterior instalación de Command Line Tools, que se obtiene gratis registrándose como Developer), la instalación de la plataforma Haskell la efectuaremos con la orden de consola:

sudo port install haskell-platform

Al instalar la plataforma tendremos instalado "Cabal". Cabal es el sistema de paquetes estándar para el software de Haskell.  Ayuda a configurar, compilar e instalar el software de Haskell y distribuirlo fácilmente a otros usuarios y desarrolladores. Ayuda con la instalación de paquetes existentes y también ayuda a los desarrolladores con sus propios paquetes. Se puede utilizar para trabajar con paquetes locales o para instalar paquetes desde archivos de paquetes en línea, incluyendo las dependencias que instala de forma automática. Por defecto está configurado para utilizar Hackage que es archivo del paquete central de Haskell y que contiene miles de bibliotecas y aplicaciones en el formato de paquete de Cabal.

Un ejemplo de utilización de Cabal para instalar paquetes de un archivo remoto de paquetes contenido en Hackage y que se llama xmonad sería utilizando la orden en línea llamada cabal:

cabal install xmonad

lo cual instalará el paquete xmonad además de todas sus dependencias.

En cuanto al editor

Siempre decimos que nuestros lectores pueden usar su editor preferido, sin embargo en este caso hay algunas restricciones. Nunca nunca usaremos editores que al tabular introduzcan caracteres no imprimibles. La razón es que Haskell es un lenguaje que ha suprimido los terminadores de línea, lo que ha conducido a usar indentación en el código. Pues bien, la indentación no es real si el editor incluye caracteres no imprimibles. Hemos visto a compañeros y profesores volverse locos tratando de entender por qué no funciona un código que a todas luces era perfecto; y no funcionaba porque la indentación estaba rota por culpa de "fantasmas no visibles" en el renglón. Recomendación: Sublime Text o Emacs ... o en el otro orden mejor.

Haskell y Emacs

Los archivos de los proyectos de Haskell son ficheros .hs. Para que Emacs pueda manejar fácilmente dichos ficheros, instalaremos en nuestro Ubuntu el paquete haskell-mode

sudo apt-get install haskell-mode

Haskell y Sublime Text

Instalaremos Sublime Text mediante:

sudo add-apt-repository ppa:webupd8team/sublime-text-3
sudo apt-get update
sudo apt-get install sublime-text-installer

Sublime Text está totalmente preparado para usar Haskell, salvo por un detalle: los caracteres no imprimibles introducidos por el tabulador. Para poder usar dicha tecla con toda comodidad y que no se incluyan estos indeseables caracteres debemos ir a

Preferences > Settings - User 

y agregar dentro de las llaves

"translate_tabs_to_spaces": true, 

El "hola mundo"

Haskell tiene un intérprete y un compilador. Saludemos al mundo primero desde el intérprete. Para ello invocaremos al intérprete desde la línea de comandos con la orden:

ghci

y el resultado será un diálogo del tipo:

Last login: Sat Sep 27 17:59:09 on console
iMac-de-fulanito:~ my_login$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude>  

Hay que saber que "Prelude" es el ambiente general mínimo de librerías y funciones cargadas al abrir el intérprete, ambiente que se puede completar a deseo del usuario.  Ahora escribiremos:

Prelude> putStrLn "Hola ... mundo!"

y al pulsar intro obtenemos el diálogo

Hola ... mundo!

Prelude>

Para salir del intérprete escribiremos

Prelude> :q

y pulsando intro saldremos a la línea de órdenes de la consola.

Si lo que queremos hacer es un ejecutable que nos permita difundir el saludo al mundo entre nuestros amigos, que puede que no tengan Haskell instalado, utilizaremos el compilador. Para ello usaremos nuestro editor preferido y con él abriremos un fichero que llamaremos hola.hs, por ejemplo. El contenido del fichero será exclusivamente la línea:

main = putStrLn "Hola ... mundo!"

Cerramos el fichero y desde la línea de órdenes de la consola ejecutamos la orden:

ghc -o hola hola.hs

por supuesto que hola es el nombre que le deseamos dar al ejecutable; además del mismo, se han creado otros dos: el hola.hi y el hola.o. Estos dos ficheros son auxiliares y necesarios para la compilación. Para ejecutar nuestro ejecutable, escribiremos en la línea de órdenes (suponemos que todo se ha llevado a cabo donde está ubicado el fichero hola.hs):

./hola

y al pulsar intro tendremos el cortés mensaje:

Hola ... mundo!

Ejemplos

Para ejemplificar el uso de Haskell podemos recurrir a funciones conocidas ya en los lenguaje imperativos y que produzcan fuerte contraste. Con nuestro editor preferido abriremos un fichero example.hs y le pondremos el siguiente contenido, que irá creciendo:

qsort [] = []
qsort (x:xs) = qsort ([y | y <- xs, y < x]) ++ [x] ++ qsort ([y | y <- xs, y >= x])

o si se prefiere, el código más elaborado y eficaz:

qsort :: (Ord a) => [a] -> [a]
qsort [] = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)

Ahora, si estamos ubicados con la consola en el directorio que contiene al fichero example.hs, tenemos dos opciones: abrir el intérprete y cargar el fichero example.hs o abrir el intérprete para él. La primera opción se materializa haciendo

ghci

pulsando intro y cuando aparezca el diálogo:

Last login: Sat Sep 27 17:59:09 on console
iMac-de-fulanito:~ my_login$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> 

entonces escribiremos:

Prelude> :l example.hs

y al pulsar intro obtendremos el diálogo:

[1 of 1] Compiling Main             ( example.hs, interpreted )
Ok, modules loaded: Main.

*Main> 

El retazo "Ok, modules loaded: Main." indica que el fichero example.hs ha sido interpretado correctamente y  el retazo de código "*Main> " indica que el ambiente Prelude ha sido completado con las funciones, tipos de datos, clases, etc. recién interpretadas en example.hs.

Ahora seremos capaces de ordenar una lista con nuestra función:

*Main> qsort ([2,-1,5,3])
[-1,2,3,5]
*Main>

¿No parece magnífico? Sin embargo no todo lo bello es apropiado.  Lo mejor para ordenar es utilizar la función primitiva sort. Pero aquí surge el primer problema:

*Main> sort([2,3,1])

<interactive>:5:1:
    Not in scope: `sort'
    Perhaps you meant one of these:
      `sqrt' (imported from Prelude), `qsort' (line 1)
*Main>

Este mensaje significa, ni más ni menos, que la función sort no está en Prelude, ni por supuesto en example.hs. Para incluirla debemos cargar un módulo instalado por defecto en el árbol de Haskell que la contenga:

*Main> :m + Data.List
Prelude Data.List >


y ahora podemos usar la función sort como sugeríamos antes. Pero obsérvese que hemos perdido nuestro contenido del fichero example.hs; ahora deberíamos recargarlo.

A veces es útil tener información sobre funciones. Podemos hacer, por ejemplo:

*Main Data.List> :t qsort
qsort :: Ord a => [a] -> [a]
*Main Data.List> :i qsort
qsort :: Ord a => [a] -> [a] -- Defined at example.hs:2:1
*Main Data.List> :i sort
sort :: Ord a => [a] -> [a] -- Defined in `Data.List'
*Main Data.List> 

Ahora sabemos que la línea

qsort :: Ord a => [a] -> [a]

define el tipo de la función qsort; debemos leerla así: si a es un objeto incluido en la clase Ord de objetos, qsort asigna a una lista de objetos a otra lista de objetos a.

Para importar varios módulos se puede proceder así:

equipo-de-fulanito:~ my_login$ ghci 
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :m + Data.List Data.Char
Prelude Data.List Data.Char>
Prelude Data.Char List> :m - Data.Char
Prelude Data.List>

o también así:

equipo-de-fulanito:~ my_login$ ghci 
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> import Data.Char
Prelude Data.Char> import Data.List as List
Prelude Data.Char List> :m - Data.List
Prelude Data.Char>

Para saber más de las órdenes básicas del intérprete podemos hacer:

Prelude> :h

Si queremos introducir nuestras funciones en el intérprete sin depender de un fichero del tipo example.hs, podemos. Habríamos de proceder así:

*Prelude> let fac n = if n == 0 then 1 else n * fac (n-1)
*Prelude> fac 25
15511210043330985984000000
*Prelude>

aunque lo mejor sería incluir en example.hs el código:

fac :: Integer -> Integer
fac 0 = 1
fac n = n * fac (n-1) 

y recargar example.hs

*Main Data.List> :l examples.hs 
[1 of 1] Compiling Main             ( examples.hs, interpreted )
Ok, modules loaded: Main.
*Main Data.List> fac 25
15511210043330985984000000
*Main Data.List> 

Si queremos una impresión de la estadística de tiempo/memoria tras cada evaluación, podemos ejecutar:

Prelude> :set +s

desharemos lo hecho con la orden:

Prelude> :unset +s

Recordemos que para salir del intérprete ejecutaremos:

Prelude> :q

Para comentar una línea la hacemos preceder de la secuencia de caractéres "--"
y para comentar un párrafo de código lo ponemos entre "{-" y "-}":

-- esta línea está comentada

{- este párrafo está comentado
    por ser sólo una explicación -}

Un ejemplo más elaborado

De D. José E. Labra G. hemos tomado el contenido ligeramente modificado de los ficheros Pila.hs y Menu.hs. El segundo es un ejemplo de menú que importa y opera con los objetos del primero.

Si queremos hacer un ejecutable con Menu.hs podemos operar de dos maneras. Suponemos que en la consola nos hemos colocado donde están los dos ficheros en cuestión. La primera forma sería:

ghc --make Menu.hs

y ahora podríamos ejecutar el ejecutable resultado con 

./Menu

La segunda forma sería ejecutar consecutivamente las siguientes dos órdenes en la consola:

ghc -c -O Pila.hs Menu.hs
ghc -o menu -O Pila.o Menu.o

y ahora podríamos ejecutar el ejecutable menu con 

./menu

La ventaja de esta última forma de proceder es que con la orden:

ghc -c -O Pila.hs Menu.hs

creamos los ficheros Pila.o y Menu.o que nos valdrían para pasarlos a otra parte del equipo que deba elaborar el fichero ejecutable menu,  pero que sin embargo no deba, o no pueda, conocer los ficheros Menu.hs y/o Pila.hs. Una vez hayan sido pasados los mencionados ficheros Pila.o y Menu.o, los receptores compondrían el fichero ejecutable menu mediante la orden de consola:

ghc -o menu -O Pila.o Menu.o

Ejecutar sin compilar y sin interpretar

Supongamos que tenemos un fichero llamado, por ejemplo,  fmapping_io.hs y con el siguiente contenido:

import Data.Char 
import Data.List 

main = do line <- fmap (intersperse '-' . reverse . map toUpper) getLine 
          putStrLn line
Podríamos ejecutarlo como sigue:

equipo-de-fulanito:~ my_login$ runhaskell fmapping_io.hs
esto es una prueba

A-B-E-U-R-P- -A-N-U- -S-E- -O-T-S-E

La principal arma de Haskell

Como explican los autores en su libro Razonando con Haskell, en muchos lenguajes imperativos (p. e. C++) con el mecanismo de paso por valor (call by value) siempre se evalúan los argumentos antes de la llamada. Una alternativa a este mecanismo es el paso por necesidad (call by need), en el cual se evalúa solamente los argumentos necesarios; el problema de tal mecanismo para los lenguajes imperativos es que su implementación es compleja.

En el contexto de los lenguajes funcionales se habla de dos modos de evaluación: impaciente (eager) y perezosa (lazy); en el primer caso el evaluador hace todo lo que puede mientras que en el segundo hace solamente lo preciso. El mecanismo impaciente corresponde al paso por valor mientras que el perezoso al paso por necesidad.

Les proponemos que tomen de nuevo su fichero example.hs y que incluyan en él el siguiente código:

desde :: Integer -> [Integer]
desde n = [n..]

suma :: Integer -> [Integer] -> Integer
suma 0 _ = 0
suma n (x:xs) = x + suma (n-1) xs

La función desde, dado un valor entero n, entrega la lista de todos los números enteros superiores o iguales a n, ordenados en el orden de los números enteros según se avanza hacia el final de la lista. Así, [0..] es la lista en orden creciente de todos los números enteros comenzando en 0: la lista de los números naturales en su propio orden.

La función suma tiene dos argumento: un número entero (que pensamos será siempre un número natural), como primer argumento, y una lista de números enteros, como segundo argumento. Su labor es sumar las n primeras entradas de la lista argumento, y si ese n fuese 0, ofrecer 0 como resultado; esto último es la condición de detención. Si se piensa bien, todo esto se puede entender como un bucle while de los lenguajes imperativos.

Pero qué pasa si nuestra malicia natural nos lleva, por afán de diversión, a hacer una jugarreta al intérprete de Haskell, pasándole como segundo argumento una lista infinita. ¿Qué espera el lector? ¿será éste el final de Haskell, de nuestra máquina y del tiempo relativista? Nada más lejos de la realidad y valga para ello el siguiente ejemplo:

ghci example.hs

y recibimos el diálogo siguiente, señal de que ¡todo ha ido bien por ahora!

GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( example.hs, interpreted )
Ok, modules loaded: Main.

Como el coyote, probemos que la trampa está hecha y funciona ... y atentos a ejecutar Ctrl + C inmediatamente después de  desde 0 o ... esto no acabará realmente.

*Main> desde 0
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,8^CInterrupted.

Seguidamente hagamos este inocente cálculo:

*Main> 1 + 2 +3 + 4 + 5
15

Finalmente pedirle al correcaminos que caiga en la trampa del precipicio infinito:

*Main> suma 5 (desde 1)
15
(0.00 secs, 1030416 bytes)
*Main>

Nos costará, si no conocemos de antes a Haskell, sobreponernos a la impresión: hemos pedido que sume los primeros 5 números de una ¡lista infinita! y ¡lo ha hecho en 0.00 segundos! ¿Dónde está el truco? Ni más ni menos en que Haskell evalúa perezosamente y al recibir la orden:

*Main> suma 5 (desde 1)

no ha: confeccionado primero desde 1, tomado luego sus primeras 5 entrada y sumado finalmente para ofrecer el resultado 15. En su lugar lo que hizo es calcular la primera entrada de desde 1, separarla y mandar que le sea sumada la segunda entrada de desde 1, la cual pasa a calcular sabiendo que queda una selección menos que hacer, etc. El proceso continúa hasta que sabemos que no queda selección de entrada alguna que hacer ya en desde 1 y entonces mandamos sumar y damos la orden de parar de sumar, para seguidamente efectuar definitivamente la suma hilvanada durante todo este tiempo.

La habilidad de Haskell: ¿para qué calcular desde 1 y luego sumar sus 5 primeras entradas, si para nuestro propósito sólo son imprescindibles esas 5 entradas? ¡cuando sea necesario calcular/extraer más entradas de desde 1, ya lo haremos! ¡No nos precipitemos haciendo más trabajo del necesario! ¡Hagamos el sucintamente imprescindible no sea que nos cansemos ... eh!

Con el código anterior hay un pequeño problema, que realmente sólo es aparente:

*Main> suma 5 [1,2,3,4]
*** Exception: example.hs:(23,1)-(24,33): Non-exhaustive patterns in function suma


*Main>

Como vemos se genera una excepción, que podría ser capturada convenientemente. Un código alternativo para la función suma podría ser:

suma :: Integer -> [Integer] -> Integer
suma 0 _         = 0
suma _ []        = error "lista demasiado corta"
suma n (x:xs) = x + suma (n-1) xs

que ahora proporciona el siguiente diálogo:

*Main> suma 5 [1,2,3,4]
*** Exception: lista demasiado corta

*Main> suma 5 [1,2,3,4,5]
15
*Main> suma 5 [1,2,3,4,5,6]
15
*Main> suma 5 (desde 1)
15
*Main>

De nada serviría la evaluación perezosa con un código como éste:

desde :: Integer -> [Integer]
desde n = [n..]

longitud :: [a] -> Integer
longitud [] = 0
longitud (x:xs) = 1 + longitud xs

sumaB :: Integer -> [Integer] -> Integer
sumaB n lst@(x:xs)
 | n == 0    = 0
 | n > len   = error "lista demasiado corta."
 | otherwise = x + sumaB (n-1) xs
             where len = longitud lst

cuando lst es infinita:

*Main> suma 5 (desde 1)

sencillamente no funciona, pues la condición de la ejecución exige hacer el cálculo de una longitud, el cual no acaba.

Otro gran recurso en la programación funcional con Haskell es la utilización en las funciones de "argumento con patrón". En la línea anterior:

suma n (x:xs) = x + suma (n-1) xs

el segundo argumento de la función suma, a saber (x:xs),  es aportado con un patrón, lo que permite un uso suyo eficiente dentro de la definición del caso:   x + suma (n-1) xs

Así es Haskell.

Nuestro reto habitual

Esta vez consiste en pensar qué significa el siguiente código Haskell, que podríamos poner en nuestro fichero Criba.hs, cargar en el intérprete y ejecutar:

module Criba (module Criba) where

criba :: [Integer] -> [Integer]
criba (p:xs) = [x | x <- xs, p `noDivideA` x]
                      where m `noDivideA` n = mod n m /= 0

primos :: [Integer]
primos = map head (iterate criba [2..])

primosEq :: [Integer]
primosEq = map head  lprimos 
           where lprimos = [2..] : map criba lprimos 

sin ánimo de producir vértigo.

No nos emocionemos demasiado, pues aunque es muy elegante no es eficiente ni la criba real; es solamente un código de gran valor pedagógico.

Enlaces de interés para saber más por sí mismo

Hemos dado la primera clase. Ahora

-) The Glorious Glasgow Haskell Compilation System User's Guide, Version 7.8.2
-) Una introducción a Haskell telegráfica y en español.
-) Podemos echar 10 minutos más bien empleados y aprenderlo casi todo.
-) Información técnica sobre los módulos. Una página similar, más antigua pero de mucho interés.
-) Wikihaskell de la UCA.
-) Una guía de usuario para Cabal y la guía de Cabal de Wikihaskell.
-) Learn You a Haskell for Great Good de Miran Lipovaca.
-) Aprende Haskell, por el bien de todos.
-) El mundo real de Haskell
-) Razonando con Haskell. Un curso sobre programación funcional.
-) Una introducción amable a Haskell

Y ... esto es todo por hoy.

viernes, 4 de julio de 2014

Un repositorio impide la actualización del software en Ubuntu 14.04

Introducción

A veces uno de los repositorios, casi siempre de entre los no oficiales, que tenemos instalados deja de estar operativo o malfunciona. Ello impide la actualización de nuestro sistema. Es el caso reciente con el repositorio de Spotify.

Supongamos que en las labores de actualización, por ejemplo al ejecutar la orden

sudo apt-get update

aparece un mensaje del tipo:

Leyendo lista de paquetes... ¡Error!
E: Encountered a section with no Package: header
E: Problem with MergeList /var/lib/apt/lists/repository.spotify.com_dists_stable_non-free_i18n_Translation-es%5fES
E: No se pudieron analizar o abrir las listas de paquetes o el archivo de estado.

lo cual hace imposible cualquier labor de actualización e instalación.

¿Qué hacer en este caso para solucionar el problema?

Inhabilitar el repositorio que da problemas

Podríamos pensar en suprimir el repositorio con Synaptic, pero ello no será viable dado que para arrancar Synaptic debe leer primero la lista de repositorios y comprobar que están activos, labor que no se podrá completar con el consiguiente cierre de la aplicación Synaptic. Por tanto debemos hacerlo a mano. Para ello editaremos el fichero que contiene la lista de repositorios:

sudo nano /etc/apt/sources.list

y comentaremos la línea correspondiente al directorio, en nuestro ejemplo la línea de Spotify que es la siguiente:

deb http://repository.spotify.com stable non-free

Para comentar escribimos el signo # al principio de la línea, con lo que nos quedará esto

# deb http://repository.spotify.com stable non-free

guardamos el cambio hecho con el editor nano y salimos. La labor está ahora hecha.

Finalización de la tarea

Para finalizar la labor quedan tres labores. La primera es borrar el rastro del problema que llevaba al informe de error:

sudo rm /var/lib/apt/lists/* -vf

Seguidamente debemos actualizar la lista de repositorios de nuestro sistema:

sudo apt-get update

y finalmente reiniciamos el sistema. Si se desea hacerlo desde la termina, ya sabemos que es con la orden:

sudo reboot

Consideraciones finales

Es posible que este directorio problemático vuelva a estar en condiciones dentro de unos días. Cuando queramos podemos hacer lo mismo que hemos hecho pero en lugar de comentar la línea, descomentándola.

Resumen

1) abrir la terminal
2) sudo nano /etc/apt/sources.list
3) comentar el renglón:
            deb http://repository.spotify.com stable non-free
    poniendo # al comienzo del mismo.
4) sudo rm /var/lib/apt/lists/* -vf
5) sudo apt-get update
6) sudo reboot

Créditos: información elaborada a partir de los sitios:

http://ubuntuforums.org/showthread.php?t=863742
http://www.adslzone.net/postt366394.html

Y ... esto es todo por hoy.

P.D.: en lugar de usar el cliente de Spotify se puede disfrutar del servicio desde https://play.spotify.com/