Cartas desde el Silicon Valley

Uno de mis libros favoritos de mi infancia y preadolescencia es ‘Lettres de mon moulin’, de Alphonse Daudet.  Significa «Cartas desde mi molino» y cuenta las impresiones del autor (parisino) en Provenza, donde pasa un larga temporada en un molino alquilado. Desde allí, envía cartas a un amigo de París, contando sus experiencias y encontronazos con el sur francés y sus habitantes.

Pues bien, quiero hacer algo similar. El friki en el fin del mundo soy yo, y el amigo lejano, eres tú. Así que a partir de este sábado, irás recibiendo tus «cartas desde el Silicon Valley». Te iré confesando mis inquietudes y embates con la fauna de esta zona tan particular de EEUU y del mundo.

En la última edición, hemos hameme-friki-mujerblado de uno de los seres más complejos del universo conocido: Las MujeresEsos seres estocásticos, no lineales e imposibles de predecir y depurar.

Hoy hablaremos de algo mucho más sencillo: Teoría de Categorías, tipos y lenguajes de programación.

Hay 10 tipos de programadores…

Los que les gustan los lenguajes dinámicos y los que les gustan los lenguajes estáticos. Asín, tal cual. No hay más.

Estoy firmemente convencido de que la gran diferencia no es de productividad ni de seguridad. Es algo mucho más personal e intrínseco del ser más profundo de cada uno.

Los que nos apuntamos al campo del tipado dinámico somos más idealistas, amantes al extremo de la libertad individual y aceptamos la responsabilidad que ella conlleva y llevamos con resignación sus (a veces) duras consecuencias.

En resumidas cuentas, somos aquellos que llevamos tatuado en el cipote LSDMCS:

La Libertad, Sancho, es uno de los más preciosos Dones que a los hombres dieron los cielos; con ella no pueden igualarse los tesoros que encierran la tierra y el mar: por la libertad, así como por la honra, se puede y debe aventurar la vida.

— Miguel de Cervantes Saavedra.

Estamos dispuestos a hacer los tests necesarios para asegurar que nuestro software funciona y no queremos que el compilador sea un impedimento para crear nuestras obras de arte. El compilador no debe jamás de interrumpirnos mientras dictamos a la máquina lo que la musa susurra a nuestros oídos.

Luego, están… «los otros».

Orden, disciplina y nada de libertinaje en la Galaxia. Ellos creen que si te dan libertad, meterás la pata, así que lo mejor es tenerte bien agarrado por los puntos y coma (por tu propio bien, que conste).

Al igual que la rueda de Samsara y las pelis de Star Wars, a veces es La Rebelión quien lleva la voz cantante y a veces es El Imperio. Hoy claramente vivimos bajo el signo del Imperio, del tipado estático, la tiranía del compilador.

ying-yang-star-wars

¿Cómo sobrevivir a estos tiempos oscuros? Hay dos opciones. Una es la de Yoda: huir de la Galaxia, recluirse en Dagobah y esperar a que escampe.

El camino fácil es.

Luego está otro más duro, menos glamuroso, pero más noble: el de Galen Erso. Adaptarse y sobrevivir en el nuevo ambiente, mientras siembras semillas de Rebelión.

galen-erso

Que trabaje el compilador

La forma de adaptarse es no luchar contra el rígido sistema de tipos que nos impone Swift, Rust, Haskell y cualquier otro de los lenguajes que hoy están de moda. Al contrario, hay que usarlo en nuestro favor, y delegar todo el trabajo pesado que podamos en él.

Y todo este rollo patatero nos lleva finalmente, a los tipos dependientes. Antes de ver qué son, veamos el problema que solucionan.

Supongamos que tenemos una estructura en Swift que representa un tablero de un juego de mesa. Las dimensiones de dicho tablero se reciben mediante un inicializador:

struct Board{

   init(size:Int){

       // blah, blah

   }

}

¿Es correcta esta definición? NO.  El size no puede ser cualquier Int. Para empezar no puede ser cero ni un número negativo. Además resulta que el tamaño máximo del tablero (size) es de 64.

¿Tenemos algún tipo que cumpla con dichas restricciones? NO. Int es un número entero, positivo o negativo, que incluye el cero y que puede valer un huevo más que 64.

¿Cómo podemos resolver esto? Pues poniendo un porrón de guards cada vez que recibimos un size, para comprobar que se encuentra dentro del rango aceptable.  Para ello tenemos que lanzar errores cuando el input está fuera del rango o devolver Opcionales. En ambos casos, nuestro código se complica innecesariamente.

Dado que según el pensamiento único vigente, todo se arregla con tipos, ¿no podríamos definir un tipo de entero que sea solo positivo y menor o igual a 64? Así sería el compilador que haría el trabajo sucio de la validaciones.

Veamos otro caso. Vamos a usar en nuestro software un Array que siempre ha de estar ordenado de mayor a menor. Una vez más, el sistema de tipos nos deja tirados y es responsabilidad nuestra el validar esta condición. ¿No podría hacerlo el compilador?

Así podríamos seguir eternamente: una tupla cuyo primer elemento siempre es menor que el segundo, un Float que sólo puede valer entre 100 y 350, etc…

¿Qué tienen en común todos estos tipos?

Tienen en común que realmente son un tipo + una condición o predicado. El tipo “bruto” es demasiado amplio y requiere una condición que limita sus valores.

Pues bien, precisamente eso es un “tipo dependiente”. Es un tipo que “depende” de sus valores (¿lo pillas?).

En el primer caso, se trata de un Int, más un predicado que indica si está dentro del rango admitido. Podríamos definirlo de esa forma, y sería el compilador el encargado de comprobar que el valor del tipo es siempre el adecuado.

¿Te suena a ciencia ficción? Con razón, joven Padawan. Son muy pocos los lenguajes que soportan esta característica. El mejor es tal vez Idris. Es un lenguaje experimental pero muy interesante y que tiene como característica principal los tipos dependientes.

¿Y en Swift qué?

En Swift todavía no tenemos nada parecido, al menos a nivel del compilador. Eso sí, se ha hablado en varias ocasiones de incluirlo en el futuro.

Mientras tanto, hay ñapas más o menos ocurrentes que consisten en crear un tipo que empaqueta a otro aplicando una condición (algo similar al funcionamiento de un Optional). El caso del tamaño del tablero, podríamos tener un tipo Size que se inicializa con un Int y si el Int está dentro del rango aceptable, devuelve el Int dentro del Opcional, y si no, devuelve nil (mediante un init?).

No es lo mismo, pero pega en el palo. Como era de esperarse, hay en GitHub una barbaridad de implementaciones. Recomiendo que eches un vistazo a Validated. De todas las chapuzas para traer tipos dependientes a Swift, hoy por hoy es la mejor.

Do not repeat yourself

Cada vez que repitas el mismo guard en una estructura o clase, para y piensa si no sería mejor usar Validated.

En resumidas cuentas, no luches en vano y abraza el Lado Oscuro de la Fuerza. Domina a ambos y siembra Rebelión mientras Vader mira para otro lado. Al fin y al cabo, lo que importa es LSDMCS.

¡Hasta la próxima!

Fernando Rodriguez

Acerca de Fernando Rodríguez Romero

Co-Founder & Trainer at @Keepcoding_es. Advanced iOS instructor at @bignerdranch. Previous life as pythonista and smalltalker. Coder, Speaker, Blogger, Dad&Cook

Share this:

One comment, add yours.

Ariel

Jajaja, Me gusto muchó este post !!!! Voy a revisar como implemento los tipos dependientes en mis proyectos

Leave a comment