Lógica sensible: observaciones sobre el acto de programar

Leonardo Solaas
Apr 16 · 10 min read

¿Qué es programar? ¿Qué tipo de lenguaje es la programación? ¿En qué consiste la actividad o (como diría Vilém Flusser[1]) el gesto de programar? Si pensamos que, en un pasado no muy remoto, era un oficio inexistente, y que ahora es clave para el funcionamiento de casi todos los aspectos de la sociedad, debe tratarse de preguntas relevantes para entender la época en la que vivimos.

No nos apresuremos, sin embargo, a dar una respuesta. No abordemos la cuestión como si ya supiéramos: al contrario, aproximémonos de a poco, observando primero desde cierta distancia al programador que lleva a cabo su tarea. ¿Qué hace? ¿Qué actitud adopta? Está probablemente sentado a la mesa, frente a un monitor, con las manos sobre el teclado. En ciertos momentos escribe algo, en otros lo vemos absorbido por lo que lee o mira en la pantalla, en otros por fin se queda inmóvil y en silencio, con la vista perdida en la ventana o el techo. Cada tanto mueve el ratón o un dedo sobre el panel táctil de la computadora y hace unos clics.

Hasta aquí, no es muy diferente de alguien que estuviera escribiendo un email, un informe para el trabajo o un artículo para la universidad. No se aparta demasiado incluso de actividades pre-computacionales, como escribir a máquina. Pero si nos acercamos un poco, lo suficiente para mirar la pantalla por encima de su hombro, vemos que el texto que escribe es bastante singular. No es un bloque de texto, sino que está partido en muchas líneas generalmente breves, de un modo que recuerda a la poesía. Mirando más de cerca, sin embargo, vemos que entre medio de palabras que suenan a inglés hay números, operadores aritméticos y lógicos, paréntesis, llaves y otros signos extraños. Parece una mezcla absurda de texto y matemática, como si se hubiera quedado a medio camino entre decir algo y sacar cuentas, sin terminar de hacer ninguna de las dos cosas.

Podemos suponer con bastante seguridad que se trata de un lenguaje. Más aún, se trata de un código, en el sentido de un lenguaje artificial, creado con una finalidad específica. ¿Cuál es esa finalidad? Allí aparece la primera diferencia importante con quien, en actitud parecida, escribe un email o un informe. Podríamos decir, en una generalización rápida y de sentido común, que el lenguaje sirve para comunicarse. Quien escribe algo lo hace para decir algo a una persona específica (como en una carta), o a una audiencia más amplia (como en un artículo). A veces incluso se dirige a alguna versión diferida de sí mismo (como en una lista de las compras o un diario íntimo). Pero el programador, en primera instancia, no se dirige a otro, ni a otros, ni a sí mismo. Programar es su manera de comunicarse con la computadora.

Hay algo extraño ahí. La idea de comunicación parece entrañar una cierta simetría. El emisor y el receptor de un mensaje se parecen en algunos sentidos importantes: ambos entienden el lenguaje utilizado para transmitir ese mensaje, y pueden por lo tanto dotarlo de una significación o un sentido. El receptor puede, al menos en potencia, responder. Pero la computadora no es una persona, no comprende lo que se le dice, y no puede responder, al menos no en el mismo código. La programación es un lenguaje intrínsecamente unidireccional. Si, a pesar de eso, podemos todavía hablar de comunicarnos, se trata en todo caso de una comunicación asimétrica entre dos entidades radicalmente diferentes.

Tal vez entonces empecemos a explicarnos esa mezcla de texto y de cálculo que veíamos en pantalla. Es un código intermedio, que tiene algo de maquinal y algo de humano. Las computadoras no hablan (todavía) en lenguaje natural, y nosotros somos incapaces de hacer sentido directamente de los datos binarios que entran y salen del procesador. Los lenguajes de programación de alto nivel son un compromiso, un territorio a medio camino donde, con cierto esfuerzo de ambas partes, dos seres tan distintos podemos encontrarnos.

Si las computadoras son nuestra propia invención, podría resultar curioso que “piensen” de un modo tan distinto. ¿Por qué no las creamos a nuestra imagen y semejanza, como cualquier dios decente? Tal vez porque no hubo un acto de creación, sino una evolución paulatina a partir de máquinas, y porque esa maquinalidad no refleja el espectro completo de las capacidades humanas, sino apenas una “especialidad” de nuestra mente, que es la dedicada al cálculo y la lógica. Las computadoras son máquinas formales, que llevan a cabo de manera muy eficiente manipulaciones simbólicas vacías de contenido.

Ahora que convivimos con ellas a diario, esa ajenidad crea todo tipo de problemas, que son en definitiva problemas de traducción, de comunicación eficaz con un otro. Por ejemplo, se abre una brecha digital entre aquellos que “hablan el lenguaje de las máquinas” y aquellos que no, generando para los primeros una nueva forma de poder y para los segundos un tipo nuevo de analfabetismo. Los que no consiguen entenderlas, y tienen dificultades incluso para utilizar una red social o hacer un trámite en la Internet, son los excluidos de este nuevo régimen. Para ellos las computadoras son tan incomprensibles y amenazantes como una invasión alienígena.

Hay toda una industria del diseño de interfaces que busca volver accesibles los aparatos y sistemas con los que tratamos a diario, por medio de la simplificación de su complejidad inherente y la presentación de una superficie tersa, “intuitiva”. Un efecto secundario de este esfuerzo por darle a las máquinas un “rostro humano” es que se vuelven cajas negras, objetos mágicos con una lógica interna impenetrable y misteriosa. Los usuarios quedamos limitados a una posición pasiva, de aceptación resignada de lo que el aparato hace, y libertad restringida a las pocas opciones que la interfaz nos presenta. Nos convertimos en algo así como una función del programa del aparato.[2]

Los programadores, en cambio, nos enfrentamos con una pantalla en blanco. La computadora está ante nosotros, bajo nuestros dedos, como una criatura dispuesta y a la espera. Las posibilidades son ilimitadas. Ya antes de escribir una sola línea tenemos que tomar decisiones varias en cuanto a herramientas y estrategias posibles para abordar nuestra tarea. Empezamos con una idea general de lo que queremos, pero para llevarla a cabo tenemos que volverla precisa, descomponerla en partes, desplegarla en pasos lógicos. Son requisitos indispensables para explicársela a la máquina. Muchas veces incorporamos, remezclamos o modificamos código existente, hecho por otros o por nosotros mismos. Pero en cualquier caso necesitamos pensar el problema, por así decir, poniéndonos en el lugar de la computadora.

No lo sentimos como un esfuerzo penoso o antinatural. Al contrario, allí reside la esencia del goce de programar. Estamos como fascinados por la exigencia de rigor formal. Quedamos capturados por ese juego. Para que el programa corra o compile, es decir, para que la máquina lo entienda (en su modo no-humano de “entender”), tenemos que adoptar o hacer carne su incapacidad absoluta para la ambigüedad o la interpretación, su rechazo a toda inconsistencia, su literalidad aplastante. Esas restricciones son la clave para acceder al poder de la herramienta que tenemos en las manos. Si en el futuro las computadoras se volvieran inteligentes de verdad, y nos comunicáramos con ellas sin más en inglés o castellano, como si habláramos con el vecino, los programadores lamentaríamos sin duda la pérdida de esa maravillosa estupidez.

Regresemos entonces a la pregunta: ¿Qué tipo de lenguaje es la programación? Hace ya casi un siglo el lingüista Karl Bühler distinguió tres funciones del lenguaje: la representativa, que expresa estados de cosas reales o imaginarios; la expresiva, que manifiesta sentimientos o estados subjetivos del emisor, y la apelativa, que se propone condicionar o alterar la conducta del receptor[3]. Un programa no es representativo (no es verdadero ni falso, aunque opera todo el tiempo con la verdad y la falsedad) y no es expresivo (no es una expresión de sentimientos, aunque puede ser apreciado como un objeto estético). Tal vez sea entonces apelativo (o imperativo), en tanto es un conjunto de instrucciones que serán procesadas por la computadora. El criterio de éxito no sería entonces la verdad ni la belleza del programa, si no la medida en que la máquina hace lo que queremos que haga.

Quienes nos dedicamos a la llamada programación creativa (como si no fuera creativo cualquier tipo de programación) establecemos también un vínculo con la función expresiva: escribimos código para generar arte (visual, sonoro, textual, interactivo…). Nos comunicamos con la máquina para comunicar a otros unas ideas, intuiciones o sentimientos muy personales. Es un curioso rodeo. ¿Qué podría llevarnos a utilizar la programación como herramienta de creación? ¿Por qué recurrir un procedimiento formal y abstracto para expresarnos? ¿Que nos llevaría, según lo que dijimos, a la extraña situación de dar órdenes para hacer poesía?

Seguramente sería muy difícil contestar esas preguntas sin pasar antes por la observación de que programar no se siente como dar órdenes. Presionar botones y girar manivelas en una máquina industrial era seguramente una actividad más imperativa, pero reducir la programación a la función apelativa del lenguaje parece una simplificación apresurada: la computadora no es un esclavo artificial, sino algo mucho más complejo. Programar es diseñar flujos de información, proyectar sistemas dinámicos, inventar las reglas de un juego. Se parece más a crear una máquina que a operarla. Solo los programas más triviales son perfectamente previsibles: apenas los algoritmos ganan un poco de profundidad, se convierten en un espacio a explorar, en una fuente de sorpresas y un objeto de investigación. Más que dar órdenes, el trato con la computadora se siente como una serie de experimentos, como un proceso lleno de marchas y contramarchas, vías muertas y hallazgos imprevistos. Pocas veces termina en el lugar que pensábamos. La computadora no responde en código, sino con lo que hace cuando el programa se ejecuta, pero aun así se establece algo muy parecido a un diálogo, en el que la iniciativa y la creatividad se distribuyen de maneras variables.

Tendríamos que pensar, por lo tanto, en una función del lenguaje que Bühler no contempló (ni tampoco Roman Jakobson cuando, tiempo después, amplió el número de funciones a seis[4]). Se trata del tipo de lenguaje que se utiliza en las reglas de un juego, o en los axiomas de un sistema formal. ¿Podríamos llamarla, quizás, función regulativa? Ciertamente, no son órdenes. Establecen restricciones, pero al mismo tiempo abren posibilidades, crean sistemas, pequeños mundos artificiales. Generan, por ende, formas de libertad. (Dejándonos llevar por ese camino, podríamos incluso preguntarnos si la libertad puede siquiera concebirse fuera del marco de un sistema de reglas de algún tipo.)

Los artistas-programadores estamos interesados en el potencial estético de estos sistemas: en todo lo que podemos hacer con la capacidad de manipulación simbólica ultrarrápida de la máquina, y que no podríamos hacer sin ella. En cierto sentido nos parecemos a un músico, que también utiliza un sistema formal para generar un código (la partitura) que otro ejecuta (el intérprete). La diferencia fundamental con este modelo clásico es que el programa puede dar un resultado diferente cada vez que corre, o variar incluso en direcciones impredecibles mientras se ejecuta, en respuesta a variables internas o externas. Nosotros apelamos a diversos recursos para encontrar las zonas de tensión más interesantes entre la regularidad y el desorden, como la utilización del azar, de la interactividad, de fuentes de información externa o de sistemas complejos.

La escritura es habitualmente lineal: a diferencia de las imágenes, que nos presentan una multiplicidad de informaciones de manera simultánea, los textos (y el habla) pueden retomar temas anteriores y adelantarse a lo que viene, pero en definitiva proceden de a una palabra por vez, en un trayecto único del principio al fin. También en este sentido la programación es extraña, porque escondido en ese texto hay un flujo del programa que da vueltas en bucles, se bifurca en condicionales, entra y sale de funciones, e incluso fluye de manera simultánea en cauces paralelos[5]. El programador debe imaginar, mientras escribe, un recorrido que sólo se hará real en el momento de la ejecución, sabiendo siempre dónde está y evitando extraviarse en ese jardín de senderos que se bifurcan. Añadiremos entonces esta característica a la lista de particularidades que venimos compilando. La programación es, en resumen, un lenguaje asimétrico, formal, ejecutable, regulativo y no lineal.

Si, después de estas reflexiones, volvemos a mirar la escena del principio, podríamos quizás verla de otro modo: puede ser que la diferencia entre los dos personajes que la habitan ya no sea tan clara, que podamos pensarlos en cambio como las dos partes de una suerte de organismo híbrido o de una simbiosis. Sucede algo allí que ni uno ni otro podrían hacer por separado. La capacidad formal de la máquina se entrelaza con la sensibilidad humana, y la abstracción convive con una serie de emociones muy reales que alimentan el acto de programar: ansiedad, frustración, perplejidad, satisfacción, sorpresa…

Varias dualidades fundamentales en la forma de organizar el mundo que heredamos de la modernidad quedan aquí suspendidas o puestas en cuestión. Es difícil, por ejemplo, trazar el límite entre la teoría y la práctica, entre lo abstracto y lo concreto, o entre la ciencia y el arte. La lógica ejecutable del programa reúne la pureza inmutable de las matemáticas con el cambio, la impredecibilidad y la autonomía de las cosas vivas. El programador y la computadora están creando juntos pequeños mundos simulados, criaturas inmateriales hechas de volátiles flujos de información.

_____________________________

Texto escrito a pedido de Ricardo Vega M. para la revista Visibles, arte y programación, de próxima edición en Santiago de Chile.

Notas:

[1] Ver Flusser, V. (1991). Gestures. Minnesota: University of Minnesota Press, 2014.

[2] Para un análisis de la relación entre usuarios (o “funcionarios”) y los programas de los aparatos que usan, ver Flusser, V. (2006). Para una filosofía de la fotografía. Buenos Aires: La Marca Editora, 2014.

[3] Bühler, K. (1934). Teoría del lenguaje. Madrid: Alianza Editorial, 1985.

[4] Jakobson expandió el esquema de Bühler con el agregado de las funciones metalinguística, poética o estética, y fática o relacional. Jakobson, R (1960). Style in language. Nueva York: M.I.T. Ver también https://es.wikipedia.org/wiki/Funciones_del_lenguaje

[5] Los llamados “entornos de programación gráfica” representan esto de manera visual, reemplazando el texto por bloques (equivalentes a funciones) conectados por líneas (equivalentes a variables). El grafo resultante trae a la superficie la estructura del programa. Por eso son un recurso didáctico valioso para introducirse en la forma de pensar de la programación.

Leonardo Solaas

Written by

I like it when small abstract worlds come to life from a set of rules: games, visualizations, generative systems, theories and works of art.