La trampa de los lenguajes como superconjuntos de otros lenguajes

La trampa de los lenguajes como superconjuntos de otros lenguajes
Sin comentarios Facebook Twitter Flipboard E-mail


Últimamente da la impresión de que todos quieren crear un superconjunto de los lenguajes que les resultan más complejos, con el fin de facilitar su uso sin perder funcionalidad. En principio es una idea muy loable y resultaría difícl entender que alguien se oponga, pero quiero mostraros algunos motivos por los que, por ejemplo, la creación de TypeScript puede ser contraproducente (y no tiene nada que ver con el hecho de ser de Microsoft, no me toméis por un maniático).


Un lenguaje básico y popular

Vamos a hacer un ejercicio de imaginación. Partamos de la suposición de que tenemos un lenguaje para dibujar en cualquier navegador, que ha sido adoptado como estándar y para el que se proponen actualizaciones que, al afectar a tantos participantes (los desarrolladores de todos los navegadores existentes) prácticamente nunca llegan, pues es difícil llegar a acuerdos.

Nuestro lenguaje se va a basar en el trazado de líneas, así que lo llamaremos LineaScript. En él, dibujar una línea constará de dos pasos: trazar un vector y darle color. A su vez, el vector se va a generar a partir de dos puntos, con sus respectivas coordenadas x e y.

// Se crean los puntos a partir de sus coordenadas
Punto origen = new Punto(1, 1);
Punto destino = new Punto(2, 3);
// Se traza el vector uniendo ambos puntos
Vector linea = new Vector(origen, destino);
// La función colorear lo dibuja usando una constante
linea.colorear(Color.Negro); 

Como veis, nuestro lenguaje puede, potencialmente, dibujar cualquier cosa, ya que todo se puede representar en función de líneas. La dificultad comienza cuando queremos dibujar una forma geométrica, no necesariamente compleja. Por ejemplo, para dibujar un cuadrado hay que hacerlo mediante bucles:

// Algoritmo para dibujar un cuadrado desde el punto 1,1 hasta el 10, 10
for (int i=1; i<10; i++)
{
    Punto origen = new Punto(i,1);
    Punto destino = new Punto(i,10);
    Vector linea = new Vector(origen, destino);
    linea.colorear(Color.Azul);
}

Y la gente se pondría de acuerdo afirmando que LineaScript es un lenguaje potente y que hay que conocer por estar soportado en todos los navegadores, pero que su aprendizaje es muy duro y su uso, tedioso.

Solucionémoslo con un nuevo lenguaje

Como nos cuesta mucho programar de forma eficiente con LineaScript y el consorcio de participantes en él no se ponen de acuerdo a la hora de actualizar el lenguaje, decidimos sacar un nuevo lenguaje mucho más sencillo, FiguraScript, que acepte toda la sintaxis de LineaScript, pero que además añada facilidades a la hora de representar figuras.

Es decir, que FiguraScript sería un superconjunto de LineaScript, por lo que nadie debe quejarse de que reinventemos la rueda. Al contrario, esto hará que mucha gente que no se atreve a programar con LineaScript se aproxime al lenguaje sin miedo.

Así, con nuestro nuevo lenguaje, sería prácticamente igual de fácil dibujar un punto, una línea o un rectángulo:

Punto origen = new Punto(1,1);
Punto destino = new Punto(2,3);
// Mantenemos el constructor de Vectores de LineaScript 
// y añadimos uno equivalente a partir de las cuatro coordenadas
Vector linea = new Vector(origen, destino);
Vector lineaEquivalente = new Vector(1,1,2,3);
// Definimos un rectángulo por cuatro puntos
Punto p3 = new Punto(1,3);
Punto p4 = new Punto(2,1);
Rectangulo rectangulo = new Rectangulo(origen,p3,p4,destino);
// Y lo pintamos con una sola llamada
rectangulo.colorear(Color.Verde);

Nadie podrá negar que nuestro lenguaje es más completo que el básico LineaScript. Permite al experimentado seguir programando como lo hacía hasta ahora, y al novato usar métodos equivalentes que requieran codificar menos líneas para obtener un mismo resultado.

Aportamos facilidad, brevedad, compatibilidad completa (no olvidemos que nuestro lenguaje es un superconjunto), sencillez… Vamos, que todo son ventajas, ¿no?

Nueva versión del lenguaje original

El gran error de nuestra iniciativa es el de pensar en el presente y no en el futuro. ¿Qué pasará cuando LineaScript saque una nueva versión más completa? Por muy lento que vaya el proceso de ampliación del lenguaje, al haber tantos interesados en mejorarlo, lo lógico es que en algún momento aparezca una nueva versión de LineaScript que aporte nueva funcionalidad, y es probable que parte de esa funcionalidad choque con lo que nosotros habíamos reflejado en FiguraScript.

Por ejemplo, puede que también exista la clase Rectangulo, pero con un constructor distinto que sólo tome un punto, el ancho y el alto del rectángulo. Quizá penséis que ése no es el peor problema, ya que si hay sobrecarga de métodos, ambas inicializaciones pueden ser compatibles.

Punto origen = new Punto(1,1);
Punto p2 = new Punto(1,3);
Punto p3 = new Punto(2,1);
Punto p4 = new Punto(2,3);
int alto = 2;
int ancho = 3;
// Creación de un rectángulo en la nueva versión de LineaScript
Rectangulo rectangulo = new Rectangulo(origen,alto,ancho);
// Mismo rectángulo en FiguraScript
Rectangulo rectangulo = new Rectangulo(origen,p2,p3,p4);

Pero es que la cosa puede ser peor, ya que a lo mejor en la nueva versión se crea una nueva función con los mismos parámetros que nosotros usábamos en FiguraScript, pero un comportamiento distinto. Por ejemplo, un constructor para un vector que reciba las coordenadas del punto de origen, una longitud para el vector y un ancho de trazado, tendría la misma sintaxis que el constructor que habíamos añadido en FiguraScript a partir de las coordenadas de dos puntos.

// Vector a partir de cuatro coordenadas en FiguraScript 1.0
Vector linea = new Vector(1,1,2,3);
// Vector a partir de dos coordenadas, longitud y grosor en LineaScript
Vector lineaGruesa = new Vector(1,1,10,2);

¿Cuál de los dos comportamientos debería implementar FiguraScript 2.0 para el constructor que reciba cuatro enteros como parámetros?

Ante esa situación, nos veremos obligados a sacar una nueva versión de nuestro lenguaje en la que haya que decidir entre dos males:

  • Adoptar la nueva sintaxis del extendido LineaScript, haciendo así que FiguraScript 2.0 ya no pueda interpretar programas escritos en la versión 1.0, al perderse la retrocompatibilidad.

  • Continuar soportando los métodos definidos en 1.0 y perder la cualidad de ser un superconjunto de LineaScript, y que no todo programador de aquel lenguaje pueda utilizar su código directamente en el nuestro.

En cualquier caso, nuestro lenguaje habrá perdido una de las cualidades de las que presumíamos originalmente, y poco a poco perderá razón de ser y probablemente acabará desapareciendo en el olvido.

¿Qué hicimos mal?

Si nosotros, de buena fe, creamos un lenguaje que facilitaba el acceso a otro más popular pero complejo, ¿qué es lo que hemos hecho mal? ¿Por qué nos tenemos que ver abocados al fracaso?

Quien conozca la Teoría de Juegos de John Nash, sabrá que el problema radica en que hemos sido demasiado ambiciosos y hemos buscado nuestro beneficio ignorando el progreso de LineaScript. Planteamos un escenario donde nuestro nuevo lenguaje iba a ser un éxito por plantear un montón de mejoras, mientras el viejo lenguaje permanecía inmóvil.

Sin embargo, la estrategia que ofrecía un mayor beneficio común era la de colaborar activamente en el desarrollo de LineaScript, de modo que su nueva versión, en la que seguirían siendo compatibles todos los programas desarrollados en versiones anteriores, además incorporase más mejoras de las que puede llegar a desarrollar sin nuestra colaboración.

Ahora cambiad “Linea” por “Java” y “Figura” por “Type”, y conoceréis mi opinión acerca del nuevo intento de Microsoft por barrer hacia su parcela.

En Genbeta Dev | TypeScript, un JavaScript supervitaminado y mineralizado cortesía de Microsoft

Comentarios cerrados
Inicio