Lenguajes de programación que todo buen programador debe conocer

Dice Bjarne Stroustrup (creador de C++) que nadie debería llamarse un profesional si no conoce al menos 5 lenguajes suficientemente diferentes entre sí. Comparto con él esa afirmación, así que he decidido hacer una lista con esos 5 lenguajes suficientemente diferentes entre sí. La razón de que sean diferentes entre sí es que implementan paradigmas distintos.

Paradigmas de programación

Cada lenguaje está moldeado en base a uno o varios paradigmas de programación. Aunque no hay una teoría con la que todos los autores esten de acuerdo, bajo mi punto de vista existen dos grandes grupos de paradigmas de programación. Imperativos y Declarativos. Los imperativos responden a la pregunta de ¿Cómo se calcula esto? y los declarativos ¿Cuál es el resultado de esto?. Otra manera de verlo es ver al paradigma imperativo como un intento de simplificar la electrónica subyacente. El paradigma declarativo por contra muchas veces se origina de la teoría matemática y posteriormente se aplica al ordenador.

Cada uno de estos paradigmas a su vez tienen más sub-paradigmas y luego existen paradigmas transversales, es decir, que se pueden aplicar (o no) tanto en lenguajes imperativos como en lenguajes declarativos.

Un buen programador necesita conocer estos paradigmas.

Prolog

Prolog es un claro ejemplo de programación lógica. Se trata de un lenguaje declarativo. Diseñado en los años 70 en Francia, Prolog tuvo mucha popularidad en el desarrollo de Inteligencia Artificial debido a sus características lógicas. En esencia, Prolog se basa en la demostración de predicados, similares a los del álgebra de predicados.

Ejemplos de lógica de predicados

Un programa Prolog es en realidad un conjunto de afirmaciones o predicados. En tiempo de ejecución se realizan preguntas sobre predicados. Prolog intenta entonces demostrar la veracidad del predicado, para ello usa el mecanismo de backtracing. Una característica muy interesante de Prolog es el pattern matching, que básicamente permite preguntar para qué valor de una variable se cumple un predicado. Esto permite realizar cosas muy interesantes:

Ahora, para saber quién es la madre de Sonia intentamos demostrar:

Y responderá X = veronica.

En predicados sin variables, Prolog solo devuelve true o false.

Existen varios compiladores/intérpretes de Prolog, siendo el más conocido SWI-Prolog, multiplataforma y con una extensa librería que incluye GUI multiplataforma y framework web. También existe GNU Prolog y Visual Prolog (antiguamente conocido como Turbo Prolog), aunque este último no se le considera Prolog auténtico por ser demasiado diferente al resto.

Haskell

Haskell es un lenguaje declarativo que implementa el paradigma funcional. Es uno de los pocos lenguajes funcionales que son 100% puros. Se entiende por puros como la capacidad de no generar efectos colaterales. Haskell es un lenguaje fuertemente tipado y deriva de la teoría de categorías. Haskell ha sido objeto (hasta cierto punto merecido) de muchas bromas sobre este asunto, ya que para la mayoría de programadores, conocer teoría de categorías no es demasiado práctico.

Otra característica de Haskell es que es perezoso, lo que significa que no calculará nada que no sea estrictamente necesario (esto puede parecer muy raro hasta que lo entiendes en la práctica).

Este código pertenece al juego de la vida de Conway que (también) implementé en Haskell, simplemente por curiosidad, ya que no está optimizado. Faltaría el módulo Reader, así que no intentéis compilarlo directamente.

Haskell como tal no tiene variables ni bucles y sus condicionales no son exactamente iguales a los de los lenguajes imperativos (aunque se use if, en el caso de Haskell son bloques que siempre deben devolver un valor).

Aunque siempre ha sido un lenguaje académico (nació en 1994, un año antes que Java), ahora ha alcanzado bastante popularidad y algunas empresas como Facebook lo usan en producción.

El compilador más conocido, capaz de generar código nativo, es GHC. Este dispone de un REPL llamado GHCi y también compila a JavaScript y se está trabajando en WebAssembly. Otro intérprete es Hugs, pero solo es compatible con Haskell98.

La forma recomendada de instalar GHC es con Stack. Usa Stack y ahórrate quebraderos de cabeza.

Otros lenguajes similares a Haskell son ElmPureScriptEta e Idris. Este último compila a JavaScript y pone énfasis en su librería, que es capaz de competir con Angular y React.

Racket (Lisp)

Lisp no puede faltar nunca. Se trata de uno de los primeros lenguajes de programación y sigue siendo tan actual como el primer día, gracias a su simple pero efectivo diseño, inspirado en el cálculo lambda de Alonzo Church. No obstante, Lisp ha evolucionado mucho, si me preguntan que dialecto/lenguaje de Lisp merece la pena aprender ahora diría Racket. Racket es un lenguaje de programación funcional y programación orientada a objetos. Racket no es 100% puro como Haskell (la mayoría de dialectos de Lisp no lo son) pero sigue siendo muy interesante. También, tiene tipado débil en contraposición al tipado fuerte de Haskell.

Racket desciende a su vez de Scheme, que es una de los ramas principales de Lisp, siendo la otra Common Lisp. ¿Por qué estas diferencias? La gente de Scheme prefiere un lenguaje elegante, lo más funcional posible mientras que la gente de Common Lisp prefirieron sacrificar eso a cambio de un lenguaje más práctico en el mundo real.

Racket cuenta con una extensísima librería estándar capaz de realizar todo lo que te imagines sin gran problema. Racket también soporta las famosas y potentes macros.

Triángulo de Sierpinski en el IDE DrRacket.

JavaScript

JavaScript está en todas partes. Es uno de los lenguajes con mayor aplicación práctica. Web, servidor, bases de datos, scripting, plugins e incluso IoT. Por eso JavaScript me parece un lenguaje que deba estar en esta lista. Y sin embargo no es fácil categorizarlo correctamente. Ante todo, estamos ante un lenguaje de programación imperativo, con orientación a objetos y buen soporte a la orientación a eventos.

Y antes de que se me venga alguien a comerme, sí, JavaScript está orientado a objetos, aunque no siguen el patrón de clase/herencia que C++ y Java tienen tan acostumbrados a la gente. La orientación a objetos por prototipos no la inventó JavaScript, sino que ya estaba en otros lenguajes como Self y más actualmente Io. Y realmente lenguajes como Python o Ruby no se alejan mucho de esto internamente.

Actualmente, con la versión ES7, tenemos muchas cosas interesantes en programación asíncrona y clases al estilo Java que no son más que azúcar sintáctico sobre el verdadero modelo de JS.

Definitivamente, JavaScript es un lenguaje muy interesante y aunque a algunas personas les pueda parecer un caos, ciertamente es muy productivo y útil. Aprovechar al máximo JavaScript requiere pensar de forma distinta a como lo harías en otros lenguajes imperativos.

C# (o Java)

C# es otro lenguaje bastante complejo, imperativo, orientado a objetos por clases, con partes de programación funcional y programación asíncrona. Pero el sistema de la orientación a objetos aquí es distinto. Aunque Alan Kay, creador de Smalltalk y casi casi de la orientación a objetos, opine que el estilo de C++ y de Java son putas mierdas, lo cierto es que es lo más usado actualmente. Herencia, clases, interfaces, etc

Personalmente prefiero C#, ya que como lenguaje es más potente que Java, pero ambos al final tienen bastantes características comunes entre sí.

Para C# el compilador más usado es Roslyn, actualmente disponible en .NET Framework, .NET Core y Mono.

Otros lenguajes parecidos son Java o si preferimos una sintaxis tipo Pascal: Delphi/Object-Pascal tiene conceptos muy similares.

Conclusión

Con esto ya tendríamos 5 lenguajes suficientemente diferentes. Ahora bien, nos hemos dejado lenguajes muy interesantes, tanto desde el punto de vista práctico como teórico. No puedo dejar de mencionar a Smalltalk por su implementación de los objetos, a C por su ligera capa de abstracción sobre ensamblador, al propio Ensamblador porque es lo que ejecuta la CPU realmente, a Python por su diseño así como su gran uso en ciencia de datos y scripts o a Rust, un lenguaje imperativo con sistema de traits, semántica de movimiento, pattern matching.

Merece también la pena mirar FORTH, SQL (quizá el lenguaje declarativo más usado del mundo) y lenguajes que se adapten bien a la programación reactiva (hay sobre todo librerías, aunque algún lenguaje como Simulink lo implementa). Mathemathica implementa también el paradigma de programación simbólica, muy poco explotado en otros lenguajes.

Estos han sido mis 5 lenguajes, ¿cuáles serían los tuyos?

Tutorial de introducción a Godot 3.0. Juego de Snake en C#

Llegó el día. Godot 3.0 salió a la luz. Se trata de una versión con muchas mejoras respecto a Godot 2.x. Se trata de un motor de videojuegos software libre, compatible con la mayoría de sistemas operativos (y consolas a través de una compañía privada). Aprovechando la ocasión voy a explicar como hacer un juego simple, usando C# y el motor 2D de Godot. Este tutorial sirve para familiarizarse con el motor.

Instalando Godot

Lo primero que tenemos que hacer es instalar Godot. Para ello vamos a la página de descarga y descargamos la versión que corresponda a nuestro sistema con Mono.

Es requisito indispensable tener instalado Mono SDK, tanto en Linux como en Windows. El Mono SDK se descarga desde http://www.mono-project.com/download/.

Una vez descargado tendremos un fichero con tres archivos. Descomprímelos en una carpeta. Ahora simplemente puedes ejecutar el fichero ejecutable.

Ventana de proyectos

Nada más arrancar tendremos una ventana de proyectos. Desde ahí podemos abrir proyectos que hayamos creado, descargar demos y plantillas o simplemente crear un proyecto nuevo.

Si le damos a Proyecto nuevo procederemos a la creación de un nuevo proyecto (¡¿qué complicado, verdad?!).

Una vez hecho esto ya estaríamos en el editor propiamente dicho.

Editor

Rápidamente cambiamos al modo 2D y hacemos zoom hacia atrás. Vamos a ajustar la pantalla. Para ello vamos a Proyecto->Ajustes de proyecto. Buscamos el apartado Display->Window y ajustamos la resolución base. Esta será la que usaremos para poner los elementos en pantalla. Después vamos a Stretch y configuramos el modo 2D y mantener el aspect ratio.

Esta configuración sirve para empezar con juegos simples en 2D puedan escalar fácilmente a distintas pantallas sin tener problemas de descuadres.

Ahora hacemos click en el más (+) para añadir un nodo a la escena.

Para nuestro juego, voy a añadir un Node2D, que hereda de CanvasItem y tiene APIs para dibujar rectángulos y círculos..

No lo tocamos y hacemos click derecho en el Nodo. Damos click a Attach Script:

Es importante tener un nombre de script distinto a Node2D. Esto puede dar problemas. Una vez hecho esto, se nos mostrará esta pantalla, que nos permite escribir el código en C#. A partir de ahora voy a usar Visual Studio Code, porque lo considero mejor para escribir código en C# que el editor de Godot. Creamos también dos Sprite hijos del Node2D. Apple y SnakeBody van a llamarse y les creamos scripts de C# también.

Dibujar en pantalla

Abrimos con el VS Code el fichero .cs que hemos creado, en mi caso, Snake.cs.

Dentro veremos una clase con dos funciones, _Ready y _Process. Estas son solo un ejemplo de las funciones que podemos sobreescribir en las clases asociadas a nodos. Otras funciones serían: _Draw, _Input. ¿Cuándo tenemos que usar cada una? Ready es una especie de constructor, ahí inicializamos todo lo que haga falta. Process es llamada constantemente, ahí hacemos las actualizaciones y comprobaciones pertinentes. Draw permite dibujar (si no trabajamos con imágenes es muy útil). Draw no se llama útil. ¿Qué tenemos que hacer en Snake.cs? Bueno, hay que tener un timer para ir generando manzanas, así como comprobar que la serpiente se ha comido la manzana.

En este código ya vemos cosas interesantes. La primera es que podemos usar cualquier librería de .NET, en este caso he usado clases que forman parte de .NET Standard pero cualquier librería que funcione con Mono debería funcionar. También se puede usar NuGet, al final, Godot tiene un fichero SLN y un CSPROJ, por lo que no es más que un proyecto normal de C#.

La segunda cosa es que hay varias funciones para interactuar con Godot en sí: GetNode (para obtener un nodo, hay que hacer casting), AddChild (para añadir un nodo a una escena) y RemoveChild (para quitar un nodo a una escena).

El código de SnakeBody.cs es más largo, pero no más complejo. Como vemos la serpiente la represento como List<Rect2>. Además hay una variable time puesta para que la serpiente vaya a trompicones (como el snake auténtico).

Se puede ver como la función DrawRect nos sirve para dibujar un rectángulo. La API no tiene pérdida y es parecida a la API de Cairo o la Canvas de HTML5.

También se puede ver como se puede usar LINQ para comprobar las intersecciones de la serpiente consigo misma (en realidad se comprueba la cabeza con el resto de trozos, ya que la cabeza es la parte que va a estar presente en todos los golpes).

Con Update se fuerza una nueva llamada a _Draw.

Por último tenemos _Input. En Godot, la entrada se maneja por acciones, una capa de abstracción. Esto quiere decir que no es recomendable comprobar si una tecla ha sido pulsada, simplemente se asignan teclas a acciones desde Godot (o desde el juego en un panel de configuración) y en nuestro código comprobar las acciones.

Crear acciones

Para crear acciones vamos a Proyecto->Ajustes de Proyecto->Mapa de entrada y creamos las acciones que creamos convenientes. Yo las he llamado move_left, move_right, move_down y move_up. Luego las asignamos teclas de forma muy intuitiva.

Con esto ya tendríamos todo para un snake completito. Si le damos a ejecutar, podemos ver el juego en acción.

Todo el código del juego lo tenéis en el GitHub de ejemplos del blog y se puede importar a vuestro Godot.

 

Al juego le faltan muchas cosas, como una pantalla de game over cuando se produce un choque. Y puntuación. Y más detalles. Pero eso ya os lo dejo a vosotros.

 

Juego de la Vida de Conway en C# con interfaz gráfica

Hoy os traigo un proyecto que realizamos Daniel Bazaco y yo. Se trata del clásico de juego de la vida, esta vez hecho en C# con .NET Core y Avalonia como librería gráfica. Funciona tanto en Windows como en GNU/Linux. El programa tiene la peculiaridad de que tiene implementados dos algoritmos totalmente distintos para el juego de la vida:

  • El clásico algoritmo de la matriz infinita.
  • Un algoritmo usando Quadtrees y tablas de dispersión optimizadas, que permite tener patrones precalculados.

La velocidad de este segundo algoritmo es muy superior a la del primero, aunque he de confesar que este segundo algoritmo no resulta evidente y tiene una desventaja en el modo gráfico. Este segundo algoritmo avanza a trompicones, por lo que no es posible realizar una animación gráfica idónea, a no ser que lo modifiquemos ligeramente. Este tercer algoritmo que es una modificación del segundo, es más lento, pero permite ser mostrado por la pantalla.

El programa admite ficheros tanto en formato estándar RLE como un formato propio, que hemos llamado Vaca. Puedes pasarte por la wiki del juego de la vida y probar los ficheros RLE que encuentres. No obstante, hay que tener cuidado, pues algunos ficheros RLE no son del juego de la vida, sino de otros juegos con normas ligeramente modificadas.

¿En qué consiste el Juego de la Vida?

El juego de la vida es un autómata celular de dos dimensiones. También se le ha categorizado como juego para cero jugadores.

El juego tiene unas normas sencillas. Cada celda puede estar viva o muerta. En la siguiente evolución, las celdas pueden pasar a vivas o muertas siguiendo este esquema:

  • Una célula muerta con exactamente 3 células vecinas vivas “nace” (es decir, al turno siguiente estará viva).
  • Una célula viva con 2 o 3 células vecinas vivas sigue viva, en otro caso muere o permanece muerta (por “soledad” o “superpoblación”).

Unas condiciones de partida determinadas podrán desencaminar comportamientos complejos y emergentes muy interesantes como las pistolas de gliders.

Uso

Pantalla de inicio de Conway

Desde aquí podemos dar a Nuevo patrón o Cargar patrón. Si le damos a Nuevo Patrón tendremos una matriz vacía y limpia. Podemos hacer click con el ratón para ir activando/desactivando las casillas. Puedes usar las teclas W, A, S y D o las flechas en pantalla para moverte por el universo infinito de Conway.

Una vez lo tengamos podemos guardarlo para no tener que volver a dibujarlo. Otra opción es cargar un patrón de la lista. Este programa admite formato RLE y Vaca, pero solo guarda archivos en formato Vaca.

Para ejecutar el juego de la vida hay tres botones importantes. El primero es Ejecutar, que ejecuta el juego de la vida indefinidamente. Se para cuando pulsamos Parar (el mismo botón).

El otro es Siguiente, que nos permite avanzar de iteración en iteración manualmente, muy interesante para observar al detalle ciertos patrones. Por otro lado tenemos Iterar N veces, que permite iterar N veces y que sirve para pruebas de rendimiento. Hay que tener en cuenta que tanto Siguiente como Iterar N veces funcionan un poco distinto con el algoritmo Quadtree (el activado por defecto), ya que este algoritmo hace varias evoluciones de golpe, para ser todavía más rápido. La parte mala es que no es posible ver en detalle cada algoritmo.

Algoritmo Matriz
Algoritmo Quadtree

Línea de comandos

Es posible ejecutar el juego de la vida en línea de comandos. Este modo permite cargar un archivo Vaca o RLE y ejecutarlo N iteraciones. Al finalizar se muestran estadísticas y se permite guardar el resultado o mostrarlo por pantalla con caracteres ASCII.

Hay dos parámetros, -i para indicar el fichero de entrada y -n para indicar las iteraciones a calcular.

Algoritmo Quadtree

¿Cómo funciona el algoritmo quadtree que tanto mejora el rendimiento del juego de la vida? Siendo sinceros, no es algoritmo sencillo o evidente. Su nombre más correcto es algoritmo Hashlife y fue descrito por Bill Gosper en los laboratorios de investigación de Xerox Palo Alto.

La idea básica es que muchas veces en el juego de la vida nos encontramos con patrones que se van repitiendo periódicamente y grandes zonas vacías.

Para ello recurre a un almacén de cuadrantes. Y es que ahora el universo ya no es una matriz infinita, sino un cuadrante. Y cada cuadrante tiene cuatro cuadrantes hijos (noroeste, noreste, suroeste y sureste), así hasta llegar al cuadrante mínimo ya no tiene hijos sino que es una celda viva o muerta. Esto evidentemente pone limitaciones al tamaño del universo, que será siempre potencia de dos.

El almacén es una tabla hash, pero no una corriente tipo HashMap de Java o Dictionary de C# sino que toma 4 elementos como índice, cuatro subcuadrantes. Si existe un elemento cuyos cuatro subcuadrantes son iguales (no se comprueba la igualdad exactamente, sería muy lento), se devuelve la siguiente iteración del cuadrante del almacén que cumple esos requisitos. De este modo no hace falta calcular los cuadrantes nada más que la primera vez que el programa se encontró con ellos.

Este sistema consume más memoria, pero mejora de forma sustancial la velocidad de ejecución. El algoritmo luego tiene bastantes más detalles (el diablo está en los detalles), pero esa es la idea principal, no calcular los cuadrantes más que una sola vez.

Descargar Conway

Podéis descargar Conway desde GitHub y compilarlo en Windows y GNU/Linux (Mac no está probado pero en principio funcionaría), con .NET Core 2.0 instalado.

Conway en GitHub

 

 

Interfaces gráficas multiplataforma en C# con .NET Core y Avalonia

Microsoft sorprendió a todos con la publicación de .NET Core el 27 de junio de 2016. Por primera vez, la plaatforma .NET se volvía multiplataforma, con soporte a macOS y GNU/Linux. Y además se volvía software libre, con licencia MIT y con un desarrollo transparente donde cualquiera puede proponer mejoras, subir parches, etc…

Esto posibilita tener soporte de primer nivel para uno de los lenguajes mejor diseñados actualmente, C#, que hasta entonces tenía un soporte de segunda en Linux, a través de Mono.

Inicialmente el soporte de Microsoft a .NET Core abarca: aplicaciones de consola, aplicaciones web ASP.NET y UWP. Mucha gente se desanimó por no tener WinForms o WPF en .NET Core. Sin embargo eso no quiera decir que no se puedan hacer interfaces gráficas en .NET Core. Aquí os presento la librería Avalonia, que aunque está en beta todavía, funciona sorprendentemente bien y en un futuro dará mucho de que hablar.

Avalonia funciona en Windows, macOS, GNU/Linux, Android e iOS. Usa XAML para las interfaces y su diseño se asemeja a WPF, aunque se han hecho cambios aprovechando características más potentes de C#. Avalonia no es WPF multiplataforma, es mejor.

Creando un proyecto

En primer lugar, tenemos que instalar .NET Core 2.0. Se descarga en la página oficial. A continuación comprobamos que se ha instalado correctamente con:

Creamos ahora un nuevo proyecto de tipo consola con new

Si todo va bien nos saldrá algo parecido a esto:

Se nos habrán generado una carpeta obj y dos archivos: Program.cs y GitHubRepos.csproj. El primero es el punto de entrada de nuestro programa, el otro es el fichero de proyecto de C#.

Vamos a probar que todo está en orden compilando el proyecto.

Añadiendo Avalonia

Vamos a añadir ahora Avalonia. Instalar dependencias antes en C# era algo complicado. Ahora es muy sencillo, gracias a la integración de dotnet con NuGet.

¡Ya no tenemos que hacer nada más! Nuestra aplicación será compatible ya con Windows y GNU/Linux. Para el resto de plataformas, hay más paquetes disponibles en NuGet, sin embargo desconozco su grado de funcionamiento. Solo he probado la librería en Windows 7, Windows 10, Ubuntu y Debian.

Program.cs

Program.cs define el punto de entrada a la aplicación. Aquí en una aplicación Avalonia podemos dejarlo tan simple como esto:

Básicamente viene a decir que arranque una aplicación Avalonia definida en la clase App con la ventana MainWindow. A continuación vamos a definir esas clases.

App.cs y App.xaml

En Avalonia tenemos que definir una clase que represente a la aplicación, normalmente la llamaremos App. Crea un fichero llamado App.cs en la misma carpeta de Program.cs, con un contenido tan simple como este:

Lo que hacemos aquí es pedir al intérprete de XAML que lea App.xaml simplemente y por lo demás, es una mera clase hija de Application.

El fichero App.xaml contiene definiciones XAML que se aplican a todo el programa, como el estilo visual:

MainWindow.cs y MainWindow.xaml

Ahora nos toca definir una clase para la ventana principal de la aplicación. El código para empezar es extremadamente simple también:

Aquí hacemos lo mismo que con App.cs, mandamos cargar el fichero XAML. Este fichero XAML contiene los widgets que va a llevar la ventana. Parecido a HTML, QML de Qt, Glade de GTK o FXML de Java o XUL de Mozilla.

GitHubRepos.csproj

Antes de poder compilar es necesario modificar el fichero de proyecto para incluir los ficheros XAML en el binario. Se trata de añadir un nuevo ItemGroup y dentro de él un EmbeddedResource.

Ahora ya podemos compilar con dotnet run.

Nos deberá salir algo como esto:

Añadiendo clicks

Vamos a darle vidilla a la aplicación añadiendo eventos. Para ello primero hay que darle un nombre al botón, un ID. Usamos Name en XAML. También usaremos un TextBlock para representar texto.

Ahora en MainWindow.cs, en el constructor, podemos obtener referencia a los objetos XAML con Find.

Y ya estaría. También comentar que la función LanzarDado puede ser async si nos conviene. A partir de ahora ya puedes sumergirte en el código de Avalonia (¡porque documentación todavía no hay!) y experimentar por tu cuenta.

Un ejemplo real, GitHubRepos

Ahora os voy a enseñar un ejemplo real de la comodidad que supone usar Avalononia con .NET Core. He aquí un pequeño programa que obtiene la lista de repositorios de un usuario y los muestra por pantalla.

Y este es su correspondiente XAML:

Adicionalmente, he usado una clase extra para serializar el JSON.

El resultado es bastante satisfactorio: