Selecciona Edición
Conéctate
Selecciona Edición
Tamaño letra
ANÁLISIS

La pereza puede ser una virtud (en los lenguajes de programación)

La pereza puede ser una virtud (en los lenguajes de programación)

La pereza en las personas no es precisamente una virtud. Nos han dicho a menudo que la pereza es la madre de todos los vicios y que es algo a evitar. Las personas perezosas suelen tener mala fama. Sin embargo, las cosas son distintas en los lenguajes de programación. Como voy a mostrar aquí, la pereza a la hora de realizar cómputos puede llegar a ser algo beneficioso, e incluso deseable.

En los lenguajes, lo contrario de la pereza es la impaciencia. Para ilustrar la diferencia, imagine que usted quiere organizar en su casa una fiesta para sus amigos y que no conoce bien sus gustos. Si es usted una persona impaciente, comprará comidas y bebidas de diversos tipos para asegurarse de que todos quedarán satisfechos. Este comportamiento tiene las ventajas de que el invitado encontrará inmediatamente el plato que le gusta, y que podrá empezar a comer (si su buena educación se lo permite) desde el minuto uno. El inconveniente es que muy probablemente sobrará la comida y la bebida que no responda a los gustos de los comensales. Es decir, usted habrá invertido recursos para nada. Eso es justo lo que sucede en un programa de ordenador escrito en un lenguaje impaciente: que realizará cálculos cuyos resultados no siempre serán necesarios.

Lo que haría un anfitrión perezoso en esta situación sería esperar a que llegasen los invitados. A medida que van llegando, les preguntaría qué es exactamente lo que desean para comer y beber, y lo encargaría a una tienda especializada. Mientras llega la comida, podría entretenerles por ejemplo con las fotos del verano. Los lenguajes perezosos se comportan exactamente de ese modo: esperan a que exista demanda para un resultado y empiezan a calcularlo a partir del momento en que es demandado. La ventaja evidente es que nunca realizan cómputos inútiles, ni necesitan memoria para almacenar resultados que no se van a usar. A cambio, la parte del programa que demanda el resultado ha de esperar a que este sea calculado.

Imaginemos que un programa necesita la secuencia de los primeros números primos, pero no conoce exactamente cuántos va a necesitar, porque esa cantidad puede ser diferente en diferentes contextos. Un programa impaciente calcularía suficientes números primos para atender a la demanda más exigente, con lo que muy probablemente calcularía primos de más. Un programa perezoso puede permitirse el lujo de “calcular” todos los primos, es decir infinitos, aunque de hecho solo calculará los que sean demandados. Veamos cómo lo hace.

Escribiré [2, 3, 4] para referirme a la lista formada por los números 2, 3 y 4. Igualmente, usaré la notación x : lista para referirme a la inclusión de x al principio de la variable lista. Por ejemplo, la expresión 1 : [2,3,4] produce la lista [1,2,3,4]. La lista de todos los números naturales empezando a partir de uno cualquiera se puede definir de esta manera:

naturalesEmpezandoEn i = i : naturalesEmpezandoEn (i+1)

 Es decir, la lista de los números naturales que empiezan en i tiene a i como primer elemento, y le sigue la lista de los naturales que empiezan en i+1. Por ejemplo, naturalesEmpezandoEn 7 es el 7, seguido de naturalesEmpezandoEn 8; es decir, 7 : naturalesEmpezandoEn 8, que es [7, 8, 9…]. No cabe duda de que esta igualdad es correcta, aunque vista como programa sugiere un cómputo infinito. La lista completa de los números naturales se obtendría mediante la expresión naturalesEmpezandoEn 0.

Para calcular todos los números primos emplearé el algoritmo conocido como la Criba de Eratóstenes, por ser este sabio griego quien lo propuso. Comienza con la lista de los naturales a partir de 2 y realiza repetidamente la siguiente operación: considera el primer número p de la lista como un número primo y a continuación elimina a p de la lista y a todos sus múltiplos, es decir, a 2p, 3p, 4p, etc. A la lista que resulte le aplica el mismo procedimiento, y así hasta el infinito. De este modo, el primer número primo será el 2, tachará el 4, el 6, el 8… Tomará a continuación el 3 y tachará el 6 (que ya estaba tachado), el 9, el 12… La Criba toma el primer número de la lista sin tachar (el 5) y tachará sus múltiplos. Usando la notación anterior, el programa que expresa esta idea es el siguiente:

primos = cribar (naturalesEmpezandoEn 2)

cribar (p : resto) = p : cribar (tacharMultiplosDe p resto)

Todas las listas que aparecen en este programa (la de los naturales, la que resulta de tachar los múltiplos de p y la de los primos) son potencialmente infinitas, pero al lenguaje perezoso no se le ocurrirá ponerse a calcularlas hasta que exista un demanda concreta. Supongamos que tenemos una función tomar que, dado un natural n, toma los primeros n elementos de una lista. La instrucción

imprime (tomar 100 primos)

genera una demanda para calcular los primeros 100 primos de la lista primos. En ese momento, el programa anterior se ejecutará para realizar el cálculo de la parte demandada de la lista. Al llegar al primo que corresponde al lugar 100, suspenderá el cálculo.

En la programación, la pereza permite separar la parte de la generación de resultados de la parte de su consumo, lo cual redunda en programas mas sencillos y modulares. La mayoría de los lenguajes de programación son impacientes. El primer lenguaje perezoso de amplio uso se diseñó a finales de la década de 1980, y fue llamado Haskell en honor al matemático estadounidense Haskell B. Curry (1900-1982). Los programas aquí mostrados están escritos en Haskell. Este lenguaje pertenece a la categoría de los llamados lenguajes funcionales y muchas empresas lo usan, en particular gran parte de la banca inglesa y alemana. Ya ven ustedes que paradoja: una institución como la banca, a la que nadie tacharía de perezosa, realiza los cálculos de las cuentas de sus clientes mediante un lenguaje perezoso. ¡Vivir para ver!

Ricardo Peña Marí. Catedrático de Lenguajes y Sistemas Informáticos. Universidad Complutense de Madrid.

Crónicas del Intangible es un espacio de divulgación sobre las ciencias de la computación, coordinado por la sociedad académica SISTEDES (Sociedad de Ingeniería de Software y de Tecnologías de Desarrollo de Software). El intangible es la parte no material de los sistemas informáticos (es decir, el software), y aquí se relatan su historia y su devenir. Los autores son profesores de las universidades españolas, coordinados por Ricardo Peña Marí (catedrático de la Universidad Complutense de Madrid) y Macario Polo Usaola (profesor titular de la Universidad de Castilla-La Mancha).


Más información