Más allá de los objetos

Durante muchos años los científicos de la computación han buscado diferentes paradigmas que permitan una mejor y más efectiva comunicación entre el programador y la computadora. De hecho, los principios que rigen la programación actual fueron diseñados aún antes de que existieran físicamente las computadoras. Por ejemplo, en la década de los treinta Alan Turing formalizó matemáticamente el concepto de algoritmo, que es la base de la resolución de problemas mediante máquinas y antecedente directo de la programación imperativa, y Alonzo Church presentó el cálculo lambda que proporciona el fundamento de la programación funcional.

El paradigma de la programación orientada a objetos (POO) básicamente consiste en que primero se describe el mundo (dominio) mediante la definición de ciertos tipos (clases), y luego se resuelve el problema deseado mediante la interacción entre los objetos (que son instancias de las clases). Es evidente que la programación POO se ha convertido en un estándar de facto para muchas de las plataformas de programación comerciales y esto no es casualidad, debido a su marcada analogía con el mundo real. Aun así, es necesario que nos hagamos la pregunta:

… ¿y qué hay más allá de los objetos?

La figura 1, muestra una clasificación de lenguajes de programación, de acuerdo a su paradigma.


Figura 1. Clasificación de los lenguajes.

Haciendo una analogía con los lenguajes humanos, sabemos que la lengua española tiene fuertes similitudes con aquellas de origen común al latín. Algo similar sucede con los lenguajes de programación, ya que 2 lenguajes provenientes de la misma familia comparten muchas características en común, mientras que lenguajes de distintas familias funcionan de forma muy diferente y por lo tanto es más difícil poder dominar ambos.

A pesar de esta gran diferencia, en los últimos años los lenguajes de una familia están incorporando capacidades de otra, generando lo que podríamos llamar lenguajes híbridos (o multi-paradigma). Tal es el caso de C#, el cual conforme su evolución, ha ido incorporando capacidades de lenguajes funcionales.

Entonces, para contestar la pregunta original, al parecer lo que está más allá de los objetos es la programación multiparadigma, especialmente la incorporación de capacidades funcionales en lenguajes orientados a objetos.

¿Y a qué se debe tanto interés? El motivo principal sin duda es aumentar la productividad del programador dotándolo de diferentes armas para resolver problemas de una manera más efectiva. Estos conceptos existen desde hace muchos años, pero actualmente toman gran importancia al reencarnar en plataformas de programación comerciales.

Programación funcional
Los lenguajes funcionales son aquellos en los que en lugar de proporcionar instrucciones imperativas (diciendo como se deben hacer las cosas), se especifican condiciones y criterios que deben cumplirse para lograr un objetivo (otros ejemplos de lenguajes declarativos son HTML, XML, ASP.NET, SQL etccétera).

La programación funcional, propone que los programas deben componerse exclusivamente de funciones, y este concepto va más allá de la idea general que tenemos de un subconjunto de código (procedimiento o método.) Al referirnos de que todo es una función debemos entender que los lenguajes funcionales puros eliminan las asignaciones, y todos los valores y resultados se encuentran en función de otros. Es por esta razón que cuando a una variable se le asigna un valor, éste jamás se modifica, de forma que se pueda asegurar la llamada transparencia referencial.

Uno de los lenguajes funcionales más conocidos es Haskell, y muchos de sus elementos han sido retomados en C#.

Expresiones lambda
En la programación funcional se hace uso extensivo de las expresiones lambda, que no son más que funciones declaradas anónimamente (es decir sin un nombre explícito) y cuyo uso disminuye la verbosidad del lenguaje (menos líneas de código) y la potencia del mismo, al poder incrustar en cualquier parte del código una función que resuelva determinada tarea.

Ejemplo en Haskell

(\pintNum -> pintNum * pintNum)

Ejemplo en C#

Func

En ambos casos si invocamos la función nos regresará el cuadrado del parámetro invocado. En el caso de Haskell, la indicación de la expresión lambda se obtiene mediante la partícula \ mientras que en C# se indica mediante => que se puede leer como va a.

Funciones de orden superior (FOS)
Las funciones de orden superior básicamente se refieren a aquellas funciones que reciben como argumentos otras funciones, o bien regresan otra función como resultado.

En el siguiente listado podemos ver la definición de una FOS, donde la función ConvertirMoneda regresará una función (específicamente un delegado) que a su vez será invocada para calcular el tipo de cambio.

public static Func

Invocación

var lobjConvertidor = ConvertirMoneda(“PESO”);
Console.WriteLine(lobjConvertidor(20));
// Regresará 200

var lobjConvertidor = ConvertirMoneda(“EURO”);
Console.WriteLine(lobjConvertidor(20));
//Regresará 300

Inferencia de tipos
Como pudimos ver, en el listado anterior se hace uso de la palabra clave var, esta palabra reservada no implica late binding sino inferencia. El compilador asigna automáticamente el tipo de dato correcto al resultado de una función sin necesidad de que se especifique explícitamente.

Haskell
:t “Hola”
Resultado:
“Hola” :: String

Los lenguajes fuertemente tipificados son importantes por la seguridad al disminuir errores en tiempo de ejecución. Así, la inferencia de tipos conserva la fuerte tipificación del dato pero aumenta la flexibilidad y capacidad para generar polimorfismo.

Recursión como manejador de control de flujo
En los lenguajes imperativos tenemos instrucciones como if, for, while para manejar el control de flujo. En la programación funcional el control de flujo se da mediante el uso exhaustivo de listas, tuplas, etcétera y el manejo efectivo de la recursividad.

El siguiente código Haskell devuelve la sumatoria de los números del 1 al 100. sum[1..100]

En C# podríamos implementar nuestro clásico arreglo y/o contador, además de un ciclo de repetición para lograr lo mismo. Sin embargo, usando las nuevas características del lenguaje podemos hacer esto: Enumerable.Range(1, 100).Sum(); En ambos casos obtengo 5050.

Limitaciones de C# como lenguaje funcional
Existen otros conceptos de la programación funcional que no se cumplen al pie de la letra en C#, dado que es un lenguaje híbrido. Sin embargo, hay soluciones funcionales por si se desea seguir estrictamente un paradigma. Un ejemplo de esto es el de la evaluación perezosa. Ésta se refiere a la capacidad de un lenguaje de programación en la cual las expresiones de determinada sentencia no se evalúan hasta que es exclusivamente necesario. En el caso de la programación funcional esto es útil toda vez de que es posible asignar listas infinitas sin provocar un desbordamiento. Con C# podemos usar evaluación perezosa mediante el uso de listas, sin embargo el CLR por naturaleza evalúa las expresiones al momento de asignarlas.

Por otro lado, tenemos el caso de la transparencia referencial, la cual se refiere a que una función dados determinados parámetros (firmas) siempre regresará el mismo resultado. Esto no se puede asegurar en C# toda vez que tenemos operadores de asignación y manejo de estado, por lo que un estado específico (en una variable o propiedad) podría modificar el resultado de una función aun con la misma firma.

Conclusión
Los paradigmas alternos de programación representan una oportunidad para acercarnos a formas de trabajo que aumentarán nuestra productividad. La tendencia va hacia los lenguajes híbridos que incorporen capacidades de distintos paradigmas. El objetivo debe ser lograr patrones y prácticas que permitan un mejor software y un menor tiempo de desarrollo mediante el uso ordenado de las herramientas y tecnologías.

Por ejemplo, en el caso de .NET, estas nuevas características del lenguaje son el mecanismo habilitador de la tecnología LINQ. Es necesario aprender a detalle lo que existe detrás de esta implementación para poder explotar la plataforma de la mejor manera.

Para los maestros y estudiantes de las carreras de sistemas, la oportunidad que nos brindan estos lenguajes es doble ya que es posible cumplir con los objetivos académicos y además al aprender estas técnicas también es posible salir preparado con un lenguaje extensivamente utilizado en el ámbito laboral.

Referencias
[msdn2.microsoft.com/es-es/library/bb943915.aspx]
[haskell.org]
[squad.devworx.com.mx/blogs/miguel]