Automágica: durante 2017 estoy trabajando bastante en Automágica, mi software para editar libros: Más información - Posts relacionados

Aprender a programar

"La formación en informática no puede convertir a nadie en experto programador, de la misma forma que estudiar pinceles y pigmentos puede hacer a alguien un experto pintor"

-- Eric S. Raymond

Lo que se necesita es practicar, practicar y practicar. Juntar horas de vuelo. Malcolm Gladwell publicó hace poco un libro en el que expone (junto con muchos otros ejemplos de otros ámbitos) que genios como Bill Gates y Bill Joy lograron sus éxitos como programadores gracias a las miles de horas que le dedicaron a esta actividad durante sus años en la universidad.

Eric Steven Raymond, también conocido como ESR, es el autor de The Catedral and the Bazar (La Catedral y el Bazar) y el responsable actual del Jargon File (The New Hacker's Dictionary). Si bien con el Jargon File obtuvo fama como historiador de la cultura hacker, se convirtió después de 1997 en una figura líder en el Movimiento del Open Source y el Código abierto. Hoy día es uno de sus personajes más famosos y controvertidos.

Fue el coordinador del cliente de correo electrónico Fetchmail. También colaboró con los modos de edición de Emacs y coescribió porciones de la biblioteca GNU ncurses.

Fuente: Wikipedia

Página web del autor: http://catb.org/~esr/

Este post es parte de Citas sobre programación.


Los chicos malos

"Esto es lo que ocurre con la gente que piensa que odia las computadoras. Lo que realmente odia es a los malditos programadores"

-- Larry Niven

Por suerte muchos mortales aún no saben de nuestra existencia :-).

Larry Niven, nacido en la ciudad de Los Angeles (EE. UU.) en 1938, es un escritor de ciencia ficción estadounidense. Conocido sobre todo como el autor de la serie Mundo Anillo y también por el universo creado bajo el nombre de Espacio Conocido (Known Space), el éxito de su carrera como escritor de ciencia ficción lo acreditan sus varios premios Hugo y Nébula. Se ha dedicado a la escritura profesionalmente desde 1963.

La mayoría de las historias de Niven tienen lugar en un universo de ficción denominado "Espacio conocido", que presenta un escenario futuro en el que la una humanidad ultratecnificada comparte los mundos de diversos sistemas cercanos al Sol con más de una docena de razas alienígenas entre las que se incluyen especies como los agresivos kzin o los cobardes titerotes de Pierson, los subyugados kdatlyno o los pulpoides Jotoki. Muchos alienígenas son encarnados en personajes que, con frecuencia, acompañan a los protagonistas o son los propios protagonistas de las novelas de Niven.

Fuente: Wikipedia

Fans club del autor: http://www.larryniven.org

Este post es parte de Citas sobre programación.


Nosotros, los programadores

"La mayoría de ustedes están familiarizados con las virtudes del programador. Son tres, por supuesto: pereza, impaciencia y orgullo desmedido"

-- Larry Wall

De las tres, la pereza es la más importante. Nos impulsa a resolver problemas. Muchas veces me encuentro escribiendo programas con el objetivo de evitar hacer tareas repetitivas, difíciles de hacer "a mano" o aburridas.

Larry Wall (nacido el 27 de septiembre de 1954) es un programador, lingüista y autor, más conocido por haber creado el lenguaje de programación Perl en 1987.

Wall es el autor del programa rn (lector de artículos de Usenet) y del casi universal patch. Ha ganado el IOCCC (concurso internacional de código C ofuscado) dos veces y recibió el primer premio de la Free Software Foundation para el avance del software libre en 1998.

Más allá de sus habilidades técnicas, Wall es conocido por su irónico sentido del humor, que manifiesta en sus comentarios en el código fuente o en Usenet. Por ejemplo (traducción libre): "No me gusta hacer cosas estúpidas, excepto si son a propósito".

Fuente: Wikipedia

Este post es parte de Citas sobre programación.


Citas sobre programación

A partir de hoy, 1º de enero, van a ir apareciendo durante siete días seguidos en este blogs citas, principalmente relacionadas con el acto de programar, que en muy pocas palabras encierran conceptos muy importantes: a veces superficialmente divertidos y otras más profundos. Además de la cita, voy a completar los posts que aparezcan con información del autor, links, fotos o alguna que otra anécdota para ilustrarla.

La primera es de Alan Kay.

"La mayoría del software actual es muy parecido a una pirámide egipcia, con millones de ladrillos puestos unos encima de otros sin una estructura integral, simplemente realizada a base de fuerza bruta y miles de esclavos" -- Alan Kay

Querido programador, espero que nunca te encuentres bajo el látigo construyendo una pirámide :).

Alan Kay, es un informático estadounidense, conocido por su trabajos pioneros en la programación orientada a objetos y el diseño de sistemas de interfaz gráfica de usuario. Kay colaboró en la creación de Squeak, un entorno para la creación y experimentación multimedia en 1995 mientras trabajaba en Apple y todavía sigue colaborando con el proyecto.

Fuente: Wikipedia


Recomendaciones al programar en Python

Esta es una traducción de la última sección del PEP 8 de Python, Recomendaciones al programar:

Programming Recommendations

El código debe ser escrito de forma que no tenga desventajas en otras implementaciones de Python aparte de CPython (PyPy, Jython, IronPython, Pyrex, Psyco).

Por ejemplo, no te bases en la implementación eficiente que tiene CPython de concatenación in-place de strings en sentencias de la forma a+=b o a=a+b. Esas sentencias corren más despacio en Jython. En su lugar la forma ''.join() debe ser usada en bibliotecas, en las partes dónde la performance sea importante. Esto asegura que la concatenación ocurra en tiempo lineal en todas las implementaciones.

La comparación con singletons como None siempre debe hacerse con is o is not, nunca con los operadores de igualdad.

También tené cuidado al escribir if x cuando realmente querés decir if x is not None, por ejemplo al testear si a una variable o argumento que por defecto es None le fue asignado a otro valor. El otro valor puede tener un tipo (por ejemplo, un contenedor) que puede ser falso en un contexto booleado! (NdT: por ejemplo [] o {}).

Usá excepciones basadas en clases

Las excepciones basadas en strings en código nuevo deben desaparecer ya que esta característica del lenguaje fue eliminada en Python 2.6.

Los módulos o paquetes deben definir su propia clase base para exepciones específica de su dominio, la cual debe extender la clase built-in Exception. Siempre incluí un docstring a la clase, por ejemplo:


class MessageError(Exception):

"""Clase base para errores en el paquete mail."""

La convención para el nombramiento de clases se aplica aquí, aunque deberías agregar el sufijo 'Error' a tus clases de excepciones, si la excepción es un error. Las excepciones que no sean errores no necesitan un sufijo especial.

Al lanzar una excepción, usá raise ValueError('mensaje') en lugar de raise ValueError, 'message'.

La forma usando paréntesis es preferida porque cuando los argumentos de la excepción son largos o incluyen formateo de strings, no necesitás usar el carácter de continuación de línea () gracias al paréntesis. La forma vieja será quitada en Python 3000.

Al atrapar excepciones, mencioná la excepción específica cuando puedas, en lugar de usar la clausula except:.

Por ejemplo, usá:


try:

    import platform_specific_module

except ImportError:

    platform_specific_module = None

Una clausula except: atrapará las excepciones SystemExit y KeyboardInterrupt, haciendo que sea más difícil interrumpir al programa con Control-C, y puede traer otros problemas. Si querés atrapar todas las excepciones que señalan errores en el programa, usar except Exception:.

Una buena regla es limitar el uso de la clausula except: a dos casos:

  1. Si el manejador de excepción estará imprimiendo o logeando el traceback; al menos el usuario se dará cuenta de que ocurrió un error.
  2. Si el código necesita hacer algún trabajo de limpieza, pero después deja que la excepción se propague hacia arriba con raise. try...finally es la mejor forma de manejar este caso.

Adicionalmente, para todas las clausulas try/except, limitá la clausula try a la absolutamente mínima cantidad de código necesario. De nuevo, esto evita esconder bugs.

Si:


try:

    value = collection[key]

except KeyError:

    return key_not_found(key)

else:

    return handle_value(value)

No:


try:

    # Too broad!

    return handle_value(collection[key])

except KeyError:

    # Will also catch KeyError raised by handle_value()

    return key_not_found(key)

Usar los métodos de string en lugar del módulo string.

Los métodos de string son siempre más rápidos y comparten la misma API con los strings unicode. Sobreescribí esta regla si necesitás compatibilidad hacia atrás con versiones de Python menores a 2.0.

Usá ''.startswith() y ''.endswith() en lugar de rebanamiento de strings (string slicing) para checkear prefijos y sufijos.

startswith() y endswith() son más limpios y menos propensos a errores. Por ejemplo:

Si: if foo.startswith('bar'):

No: if foo[:3] == 'bar':

La excepción es sin tu código debe funcionar con Python 1.5.2 (pero esperemos que no!).

La comparación entre tipos de objetos debe usar siempre isinstance() en lugar de comparar tipos directamente.

Si: if isinstance(obj, int):

No: if type(obj) is type(1):

Al chequear si un objeto es un string, recordá que hay strings Unicode también! En Python 2.3, str y unicode tienen una clase base común, basestring, así que podés hacer:

if isinstance(obj, basestring):

En Python 2.2, el módulo types tiene el tipo StringTypes definido para ese propósito, por ejemplo:


from types import StringTypes

if isinstance(obj, StringTypes):

En Python 2.0 y 2.1, tenés que hcaer:

from types import StringType, UnicodeType

if isinstance(obj, StringType)

o


isinstance(obj, UnicodeType) :

Para secuencias, (strings, listas, tuplas), hacé uso del hecho de que las secuencias vacías tienen valor de verdad falso:

Si:


if not seq:

if seq:

No:


if len(seq):

if not len(seq):

No escribas strings literales que hagan uso de espacios en blanco al final de una línea. Esos espacios en blanco son visualmente indistingibles y algunos editores (o más recientemente, reindent.py) los eliminan.

No compares valores booleanso con True o False usando ==.

Si:

if greeting:

No:

if greeting == True:

Peor:

if greeting is True:

Programar

Estoy leyendo el libro Structure and Interpretation of Computer Programs.SCIP

De su primer capítulo:

Vamos a estudiar la idea de proceso computacional. Los procesos computacionales son seres abstractos que habitan las computadoras. A medida que evolucionan, los procesos manipulan otras cosas abstractas llamadas datos. La evolución de un proceso es dirigida por un conjunto de reglas llamado programa. Las personas crean programas para dirigir procesos. En efecto, conjuramos los espíritus de las computadoras con nuestros hechizos.

Un proceso computacional es, en efecto, como la idea que tiene un hechicero de un espíritu. No puede ser visto o tocado. No está compuesto de materia. Sin embargo, es muy real. Puede realizar trabajo intelectual. Puede responder preguntas. Puede afectar el mundo desembolsando dinero en un banco o controlando un brazo robótico en una fábrica. Los programas que usamos para conjurar procesos son como los conjuros de un hechicero. Ellos son están hechos a partir de expresiones simbólicas y esotéricos lenguajes de programación que prescriben las tareas que queremos que nuestros procesos realicen.

Un proceso computacional, en una computadora funcionando correctamente, ejecuta programas en forma precisa y exacta. Así, al igual que un aprendiz de hechicería, los programadores novicios deben aprender a entender y anticipar las consecuencias de sus conjuros. Incluso los errores pequeños (usualmente llamados bugs) en los programas pueden tener complejas e inesperadas consecuencias.

Afortunadamente, aprender a programas es considerablemente menos peligroso que aprender hechicería, por que los espíritus con los que lidiamos están convenientemente contenidos de forma segura. La programación en el mundo real, sin embargo, requiere cuidado, experiencia y sabiduría. Un pequeño error en un programa para diseño asistido por computadora, por ejemplo, puede llevar al colapso catastrófico de un avión o un dique o a que un robot industrial se auto destruya.

Los grandes ingenieros de software tienen la habilidad de organizar los programas de forma tal que que pueden estar razonablemente seguros de que el proceso resultante realizará las tareas que se deseaban. Pueden visualizar el comportamiento de sus sistemas. Saben como estructurar los programas de forma que los problemas no anticipados no lleven a consecuencias catastróficas, y cuando los problemas aparecen, pueden debugear sus programas. Los sistemas computacionales bien diseñados, como los automóviles o reactores nucleares bien diseñados, son diseñados en forma modular, de esta forma las partes pueden ser construidas, reemplazadas y debugeadas en forma separada.


Clausuras en Python

Hace unos días leí este post en el blog de Javier Smaldone.

Closures: Essentially a closure is a block of code that can be passed as an argument to a function call.

Como parte de la didáctica Javier iba mostrando ejemplos que resolvía con algún lenguaje sin Clausuras (como Java o PHP) y con Ruby (el post trata sobre las Clausuras como una fortaleza de Ruby). Mientras leía fuí resolviendo los mismos ejemplos en Python y los dejé en forma de comentos. Como la identación no salió muy bien, los reproduzco aca:

Juanjo:

Las que siguen son soluciones en Python de los ejemplos que planteaste, algunas usan clausuras, otros puede que no :)

El ejemplo simple:

Supongamos que deseamos escribir una función que tome como parámetro un arreglo de valores enteros y retorne otro arreglo, producto de multiplicar por 2 cada uno de los elementos del parámetro.
def f(a):

    return [2*x for x in a]

El ejemplo de people:

Supongamos ahora que tenemos una clase "Person", cuyo método "age" calcula la edad de la persona. Si tenemos una colección de personas en el arreglo "people" y deseamos obtener sólo aquellas que son mayores de 18 años.
[p.name for p in people if p.age > 18]

Problema 1:

Convertir las cadenas de un arreglo a mayúsculas.
a = [x.upper() for x in a]

Problema 2:

Dado un arreglo de la forma [["nombre", "apellido"]], obtener un arreglo de la forma ["apellido, nombre"]. Por ejemplo, dado:
[["Javier","Smaldone"],["Santiago","Lobos"],["Bon","Scott"]]
obtener:
["Smaldone, Javier", "Lobos, Santiago", "Scott, Bon"]
[”, “.join([y,x]) for [x,y] in a]

Problema 3:

Listar los nombres de las personas mayores de edad y mostrar la edad promedio de las mismas (según el ejemplo planteado anteriormente).

Este no quedó tan bien como los otros, pero te dejo mi interacción en REPL de Python:

>>> p1 = Persona()

>>> p1.age = 19

>>> p1.name = “Juan Hewr”

>>> p2 = Persona()

>>> p2.age = 2

>>> p2.name = “Baby Jones”

>>> p3 = Persona()

>>> p3.age = 30

>>> p3.name = “Sussan Ahoria”

>>> people = [p1, p2, p3]



>>> s = 0.0

>>> adults = [p for p in people if p.age > 18]

>>> for p in adults:

print p.name

s += p.age

Juan Hewr

Sussan Ahoria

>>> print s/len(adults)

24.5

Problema 4:

Dado un arreglo de cadenas, obtener la de mayor longitud.
max(cadenas)

Javier:

Muchas gracias Juanjo por las soluciones.

Con respecto al problema 4, un detalle:

En Ruby también puedes obtener el máximo elemento de un arreglo ‘a’ usando

a.max

Sin embargo, la idea era mostrar como aplicar una función al estilo del ‘fold’ de los lenguajes funcionales. ¿Podrías reescribir la solución en esos términos?

Juanjo:

Primero una aclaración de algo que me pasé por alto: max(a) en Python cuando a es una lista de strings no da el string más largo sino el que está más al final en un ordenamiento creciente alfabético estando las minúsculas después que las mayúsculas. Es así también en ruby?


>>> max(”hola”, “juanjo”)

‘juanjo’

>>> max(”hola”, “Juanjo”)

‘hola’

>>> max(”a”, “A”)

‘a’

>>> max(”a”, “AAAAAAAAAAAAAAAAAAAAAa”)

‘a’

>>> max(”a”, “AAAAAAAAAAAAAAAAAAAAA”, “a”)

‘a’

>>> max(”AAAAAAAAAAAAAAAAAAAAA”, “a”)

‘a’

>>> max(”b”, “a”)

‘b’

>>> max(”B”, “a”)

‘a’

Javier:

Así es, Juanjo. Yo también me equivoqué. max, aplicado a strings devuelve el máximo según el orden lexicográfico, y no según la longitud.

Me sigue quedando la duda. ¿Hay algo similar a ‘inject’ o ‘fold’ en Python?

Juanjo:

Ahora si vamos a intentar resolver el ejemplo 4 en Python:

Mmm inject está bueno para resolver ese problema.. pero creo que no tenemos algo así en Python. Intentemos de todas formas:

Tenemos una lista de strings:

a = [”hola”, “juAnjO”, “Argentina”, “8″]

Una función ‘criterio’:

def longer(a, b):

    if len(a) > len(b):

        return a

    else:

        return b

And this magic functions called ‘mas’:

def mas(l, c, v):

    if l:

        return mas(l[1:], c, c(l[0], v))

    else:

        return v

Que nos va a permitir hacer algo como esto:

>>> mas(a, longer, “”)

‘Argentina’

Mirando desde más cerca.. esta función ‘mas’, es muy parecida a ‘inject’, salvo por el nombre :)

>>> inject = mas

>>> numeros = [1,2,3,4,5,6]

>>> def suma(a, b):

    return a + b

>>> inject(numeros, suma, 0)

21

Mmm parece que funciona, comprobemoslo:

>>> sum(numeros)

21

Si!

Nos leemos!


Contribución recibida para la página de Paradigmas!

Mantengo esta página con ejercitación y otra documentación sobre la materia Paradigmas de Programación que se dicta en la Facultad Regional Santa Fe de la Universidad Tecnológica Nacional, la semana pasa recibí este mail:

Hola, acabo de rendir Paradigmas y para eso con un compañero hicimos

varios finales.

La verdad hubiese estado bueno si alguien los hubiese hecho y posteado

por ahí. Como ustedes hicieron una página con cosas de Paradigmas, se

nos ocurrió pasárselos y ver si los pueden subir para que le sirvan a

alguien más.

Salu2

Los archivos que recibí ya fueron subidos a la página, si cursaste Paradigmas, la estudiaste, la rediste y en el proceso creaste una biblioteca de funciones o resolviste problemas y querés compartirlos con otros estudiantes, mandáme un mail!



¿Es el software un arte?

Con esta pregunta empieza el primer capítulo de un libro llamado Programando como es debido, es parte de una colección publicada a mediados de los 80' llamada Biblioteca Básica Informática. La primera vez que me crucé con estos libros estaba en la escuela secundaria, el padre de un amigo los tenía y también estaban en la biblioteca de mi escuela. Era entretenido hojearlos, una especie de paleontología de la informática :-)

En Santa Fe, en una casa de canje de libros en el centro (25 de Mayo, entre Crespo e Hipólito Irigoyen) pueden conseguirse algunos de los libros de esta colección por $2. Tengo algunos en mi biblioteca. Mientras estudiábamos, un amigo tomó uno y empezó a leer. Es muy interesante prestar atención, sobre todo en los tiempos que corren, a lo que se pensaba hace 20 años:

"¿Es el software un arte? Esta pregunta, realmente crucial, afecta hoy en día no sólo a los usuarios, sino también a una gran cantidad de empresas interesadas en transformar esta actividad artesanal en indutria. The art of programming: así se titula el talismán para el programador, una monumental enciclopedia del Software, escrita por Knuth, uno de los genios en esta materia. En sus muchos tomos el autor pasa lista, explicándolos y clasificándolos, a la mayor parte de los tipos de algoritmos usados en la programación. Muchas veces ocurre que principiantes y semiexpertos copian un procedimiento de una revista o un libro, que a su vez, está recogido de esta fuente sagrada del software.

No hay que escandalizarse por ello. Además, auqneu esto sirva desde un punto de vista general. Es muy difícil, cuando se tiene un problema particular, encontrar una receta adecuada precisamente para nuestro caso. Quizá exista en algún sitio (casi está ya todo inventado en este mundo), pero ¿dónde? En estos casos no queda más remedio que arreglárselas solos. Por desgracia, a menudo surge la inquietante pregunta: si, estoy dispuesto, ¿por dónde empiezo?

En la programación, efectivamente, hay ocasiones en las que la flexibilidad y la libertad de acción se traducen en tragedia, peor incluso que la del célebre asno que, puesto delante de dos montones de heno, se murió de hambre por no saber por cuál decidirse. En el caso del software, más que de dilema se debería hablar de multidilemas (dilemas super ramificados); las reglas (sentencias, bucles, GOTO) en realidad son pocas, pero ¿cómo se pueden combinar adecuadamente? Que nosotros sepamos, hasta ahora nadie ha conseguido hacer otra cosa que no sea proporcionar ejemplos, recomendando que, en casos semejantes, se procesa "por analogía" [...]

En definitiva, ¿quiere todo esto decir que el software es un arte? Según nuestro punto de vista sí, a pesar de los desesperados esfuerzos para producirlo de manera, incluso, "automática", mediante los más dispares métodos [...]

En los casos inéditos o, lo que es lo mismo, en nuestros problemas reales, estamos otra vez como al principio: la pantalla (o la impresora) permanecen inactivas: necesitan una idea, lo mismo que nos ocurre a nosotros.

Como muchos ya saben, la idea de partida, ésa que puede llegar mediante la intuición creativa, por obra y gracia de la meditación trascendental, o por cualquier otro medio por raro que pueda parecernos, se llama algoritmo, término que deriva del nombre del matemático árabe Al-Khuwarizmi. Un algoritmo es un conjunto de reglas o formas de actuar para la resolución de un problema.

[...]

Los especialistas ofrecen infinidad de variantes de este esquema (N del R: algoritmos para pensar algoritmos), pero en todas ellas hay un punto en común: el comiendo es buscar un Algoritmos Resolutorio, y éste es el punto más delicado de todo el proceso.

Sin embargo, no queremos desanimar a los que se acercan por primera vez a un ordenador. El sogware es un arte, pero también se puede aprender; para las personas con fuerza de voluntad se trata de un desafío exitante y estimulante."