Entrevista a Jeffrey Ullman (ACM Turing Award)
Pionero en los fundamentos de los compiladores y los lenguajes de programación.
Esta entrevista fue originalmente realizada en inglés por email. Por tanto, primero se ofrece una traducción al español, y al final, se encuentra la versión original.
This interview was originally conducted in English by email. The Spanish translation is provided first, followed by the original version.
Jeffrey Ullman ganó, junto a Alfred Aho, el Premio Turing de la ACM en 2020 por sus aportes fundamentales a los compiladores y a la teoría de los lenguajes de programación.
Autor de multiples libros que, con el paso de los años, se han consolidados como clásicos de la ciencias de la computación. El «libro del dragón», como se conoce a Compilers: Principles, Techniques and Tools (1985), hoy, más de tres décadas de su publicación, se considera la «biblia» de los compiladores y ha marcado a una generación de entusiastas de la computación. También es autor de libros sobre bases de datos, teoría de la computación, mineria de datos y de algoritmos y estructuras de datos.1
Y, como se puede ver en esta entrevista, nada relacionado con la computación le es ajeno. Conversamos sobre el origen de la icónica portada del «libro del dragón» —donde aparece un guerrero enfrentando a un dragón—, sobre sus reflexiones en torno a la Inteligencia Artificial Generativa, e incluso sobre qué estrategias recomienda para hacer investigación. Deja, además, consejos que merecen ser recordados.
Le estoy profundamente agradecido a Jeffrey por su generosidad a la hora de responder a mis preguntas.
¡Espero la disfruten!2
Versión traducida
(1) Me gustaría empezar con una curiosidad. Cuando entrevisté a Alfred Aho, no pude evitar preguntarle cómo surgió la idea del dragón de la portada de «Principles of Compiler Design», y me respondió: «La idea del dragón de la portada de nuestro libro de 1977, 'Principles of Compiler Design', se debe a Jeff Ullman. La portada es una alegoría basada en 'Don Quijote', la novela épica de Miguel de Cervantes publicada en 1605». Así que me gustaría preguntarle a usted cómo se le ocurrió la conexión con Don Quijote, ya que resuena profundamente entre los lectores de habla hispana.
A decir verdad, no estaba seguro de que la teoría que promovíamos en el Libro del Dragón (Dragon Book) fuera realmente a ser eficaz. Así que en la portada puse un dibujo que sugería que los métodos que promovíamos, como el análisis sintáctico LR(k) o la traducción dirigida por sintaxis, eran realmente eficaces para «matar al dragón», que era el objetivo de facilitar la escritura de compiladores. Pero luego, para reconocer mi preocupación de que la teoría en realidad no iba a ser tan eficaz, sugerí que en realidad solo estábamos «luchando contra molinos de viento», como dice la expresión (sin duda derivada del libro de Don Quijote). Irónicamente, las herramientas específicas que mencionamos sí resultaron ser muy eficaces, aunque otras partes de un compilador nunca se doblegaron realmente a la teoría en gran medida.
(2) En su artículo de la conferencia del Premio Turing de 2020, «Abstractions, Their Algorithms, and Their Compilers» (Las abstracciones, sus algoritmos y sus compiladores), termina con la siguiente frase: «Sería muy beneficioso contar con abstracciones que orienten la creación eficiente de aplicaciones robustas mediante aprendizaje automático». Ahora, en 2025, con la adopción generalizada de la IA generativa, ¿cómo ve el futuro de la abstracción, considerando que el código es generado cada vez más no solo por humanos sino también por sistemas de IA?
En todo caso, la situación es peor. Todavía no tenemos ninguna teoría útil para responder a muchas preguntas sobre las redes profundas (deep nets), por ejemplo, que tan propensa es a clasificar erróneamente ante pequeños cambios en la entrada (p. ej., una foto de un gato se clasifica como un perro cuando cambias 10 píxeles). Y los LLM (Modelos de Lenguajes Colosales) son aún más opacos. No tenemos ni idea de cómo prevenir los «jailbreaks», por ejemplo, casos en los que un LLM revela información para la que fue específicamente entrenado para no divulgar.
También menciona el código generado por LLM. Creo que las abstracciones son especialmente importantes cuando quieres dar al LLM una instrucción (prompt) que te consiga el código correcto. Necesitas poder describir lo que quieres que haga el código, pero de una manera abstracta que transmita la idea en mucho menos espacio que el código que se va a generar.
(3) Ser autor de libros de informática tan populares es bastante poco común. ¿Cómo fue la experiencia de escribir tantos libros influyentes y verlos alcanzar una difusión tan amplia? ¿Qué significa escribir para usted?
Cuando empecé a trabajar en Bell Labs, y John Hopcroft estaba de año sabático en nuestro grupo, me dijo: «Ullman, si queremos ser famosos, tenemos que escribir un libro». Así que acordamos trabajar sobre teoría de autómatas, porque ambos habíamos estudiado el tema y el libro existente era, en nuestra opinión, demasiado difícil de leer para los estudiantes. El primer libro que hicimos fue un desastre. No sabíamos escribir y cometimos muchos errores que no se corrigieron hasta que estuvimos en las pruebas de imprenta (galeradas), cuya corrección fue muy cara para el editor; no estaban contentos con nosotros. Ahora, no solo la tecnología es más simple, por lo que las correcciones son fáciles, sino que, como con cualquier cosa, cuando la practicas lo suficiente, acabas haciéndolo bien. Así que producir libros en serie se volvió para mí más rápido y fácil.
(4) En su larga carrera en ciencias de la computación, ha trabajado en lo que podría llamarse el «núcleo» de la disciplina: compiladores, algoritmos, lenguajes de programación, bases de datos. ¿Qué —o quién— le inspiró en su juventud a abordar estos desafíos fundamentales? Le pregunto esto porque vivimos en un mundo cada vez más especializado donde a menudo se pasan por alto los fundamentos.
En los primeros días de la ciencias de la computación, había muy poco contenido y muy pocos tipos diferentes de software que fueran significativos. Incluso las bases de datos no eran realmente «algo» establecido hasta mediados de la década de 1970. Así que podías saber algo de casi todo lo que se consideraba «ciencia de la computación». Dicho de otro modo, todo lo que teníamos disponible como desafíos estaba en un área que ahora consideramos «fundamental».
(5) Durante décadas, la informática ha oscilado entre la búsqueda de fundamentos formales y la presión por soluciones pragmáticas. ¿Cómo ha vivido usted esa tensión entre la elegancia teórica y la utilidad práctica? ¿Cree que ahora estamos más cerca de reconciliar estas dos dimensiones, o más lejos?
Diría que ligeramente más cerca. No es que la teoría y la práctica tengan que reconciliarse, sino que los líderes en muchos campos han reconocido que la teoría tiene un papel que desempeñar en el desarrollo de software útil. Al principio, realmente no teníamos idea de qué tipo de teoría sería útil, así que la gente hacía prácticamente lo que quería y lo llamaba «teoría de las ciencias de la computación». Irónicamente, fue el éxito de cosas como la teoría del análisis sintáctico (parsing), donde matemáticas sofisticadas realmente redujeron el tiempo necesario para diseñar e implementar un analizador sintáctico (parser) de meses a horas, lo que hizo creer a la gente que todo iba a someterse a una teoría. Llevó un tiempo darse cuenta de que eso era falso. Algunas cosas son realmente mejores porque a alguien se le ocurrió la abstracción correcta o el enfoque matemático adecuado, pero otras cosas simplemente no parecen tener una teoría útil.
(6) A lo largo de su carrera, ha abordado algunos de los problemas más fundamentales de la informática. ¿Cuál diría que ha sido el problema técnicamente más desafiante al que se ha enfrentado y cómo lo abordó para resolverlo, tanto intelectual como prácticamente?
Bueno, nunca tuve la paciencia para trabajar en algo durante más de una semana. Pero déjeme hablarle del desafío que finalmente se llamó «Datalog». Alrededor de 1983, noté que la comunidad de IA trataba los datos de forma muy parecida a la comunidad de bases de datos, pero en lugar de usar lenguajes como SQL que eran tanto tratables (las consultas podían ejecutarse en tiempo polinómico) como optimizables (SQL, al menos en su núcleo, es lo suficientemente simple como para saber si dos consultas eran equivalentes en lo que hacían), la IA buscaba formas de lógica cada vez más complejas que, si bien podían expresar más que SQL, no eran ni tratables ni optimizables. Así que me propuse plantear una versión de la lógica —colecciones de cláusulas de Horn de primer orden («si esto y esto y... entonces aquello»)— que pudiera hacer lo esencial de SQL, pero que también pudiera hacer recursión, algo que el SQL de la época no podía. Este lenguaje, «Datalog», también era tratable y, como demostró la investigación posterior, bastante bien optimizable.
Pero el gran desafío fue político y se extendió durante décadas. A la gente de IA no le gustó porque era demasiado débil, y a la gente de bases de datos no le gustó porque no veían la necesidad de la recursión. Una forma de recursión inspirada en Datalog finalmente se incorporó al estándar SQL98 y ahora es implementada por los principales proveedores. Uno de los algoritmos de optimización que surgió de la investigación de Datalog —los «conjuntos mágicos» («magic sets»)— se implementó, pero en otro contexto inesperado, en el compilador SQL de IBM incluso antes de eso. Fue implementado a escala por LogicBlox y se ha utilizado de diversas formas inesperadas, p. ej., el uso de Joe Hellerstein en el análisis de sistemas distribuidos o el uso de Monica Lam en la optimización de código.
(7) Espero que esto no suene a cliché, pero es una pregunta que despierta curiosidad. ¿Qué consejo le daría a un joven investigador que espera hacer contribuciones significativas a la informática en esta era de cambios rápidos, donde tendencias como la IA y los enfoques basados en datos a menudo acaparan la atención?
Aquí va una sugerencia con la que pocos están de acuerdo, pero que en la práctica es bastante buena. La gente asume que la forma de investigar es leer todo sobre un campo y luego abordar uno de los problemas abiertos que encuentras al final de algunos artículos. Creo que eso es un error por la siguiente razón. Alguien puede ver un problema real, uno que realmente necesita una solución. Intenta resolverlo, avanza algo, pero no lo resuelve del todo. Así que escriben un artículo y, al final, sugieren que alguien complete la solución. Otra persona lee ese artículo. Tampoco puede resolverlo, pero realmente no conoce la necesidad práctica que abordaba el artículo. Para ellos era solo una cuestión abstracta. Así que juguetean con ello, encuentran algo cercano a lo que es el problema abierto, pero que quizás no aborda realmente el problema central, y escriben un artículo al respecto y lanzan algo que no pudieron hacer como un «problema abierto». Una tercera persona toma ese artículo, tiene menos comprensión del problema real, pero resuelve una parte del «problema abierto» y plantea otra cosa como abierta. A medida que este proceso continúa, los artículos se alejan cada vez más del problema real, y la gente simplemente escribe artículos cuyos resultados no son realmente útiles. La conclusión es: «no confíes en que valga la pena resolver un problema solo porque alguien más diga que está 'abierto'».
Lo que solía decir a mis estudiantes es que lean lo suficiente para entender la terminología y las abstracciones o modelos básicos que tiene un campo, pero que luego sigan su propio camino. Elijan un problema cuya solución sea útil y vean si pueden resolverlo. Luego tienen que revisar la bibliografía para asegurarse de que lo que han hecho es verdaderamente original. Ocasionalmente, su búsqueda descubrirá algo que está incómodamente cerca de lo que han hecho, y tienen que reconocerlo. He visto esfuerzos perdidos por ese efecto. Pero es raro. Más a menudo, lo que tienen es nuevo. Y como empezaron con un problema cuya utilidad identificaron ustedes mismos, saben que lo que tienen merece la pena.
Original
(1) I'd like to start with a curiosity. When I interviewed Alfred Aho, I couldn't help but ask about how the idea for the dragon on the cover of "Principles of Compiler Design" came about, and he replied: "The idea for the dragon on the cover of our 1977 book 'Principles of Compiler Design' is due to Jeff Ullman. The cover is an allegory based on 'Don Quixote', Miguel de Cervantes' epic novel published in 1605." So I’d like to ask you how the connection with Don Quixote came to you, as it resonates deeply with Spanish-speaking readers.
To tell the truth, I was not confident that the theory we were promoting in the Dragon Book was really going to be effective. So on the front I put a drawing that suggested the methods we were promoting, like LR(k) parsing or syntax-directed translation were really effective in "slaying the dragon," which was the goal of making it easier to write compilers. But then, to acknowledge my concern that the theory wasn't actually going to be that effective, i suggested that we were really just "tilting with windmills," as the expression goes (undoubtedly derived from the don Quixote book). Ironically, the specific tools we mentioned did turn out to be very effective, although other parts of a compiler never really yielded to theory to any great extent.
(2) In your 2020 Turing Award lecture article "Abstractions, Their Algorithms, and Their Compilers", you end with the following sentence: "Abstractions that could guide the efficient creation of robust applications using machine learning would be very beneficial." Now, in 2025, with the widespread adoption of generative AI, how do you see the future of abstraction, considering that code is increasingly being generated not only by humans but also by AI systems?
If anything, the situation is worse. We still have no theory that is useful for answering a lot of questions about deep nets, e.g., how prone is it to misclassifying under small input changes (e.g., a cat picture gets classified as a dog when you change 10 pixels). And LLMs are even more opaque. We have no idea about how to prevent "jailbreaks," for example, where an LLM will give out information that it was specifically trained not to do.
You also mention LLM-generated code. I think abstractions are especially important when you want to give the LLM a prompt that will get you the right code. You need to be able to describe what you want the code to do, but in an abstract way that gets the point across in much less space than the code to be generated.
(3) Being the author of widely popular computer science books is quite uncommon. What was the experience like of writing so many influential books, and seeing them become so widely read? What does writing mean to you?
When I started working at Bell Labs, and John Hopcroft was on sabbatical in our group, he said to me "Ullman, if we want to be famous people, we have to write a book." So we agreed to work on automata theory, because we both had studied the subject and the existing book was, we felt, way too hard for students to read. The first book we did was a mess. We didn't know how to write, and we messed up a lot that didn't get fixed until we were in page proofs (which were very expensive for the publisher to fix -- they were not happy with us). Now, not only is the technology simpler, so corrections are easy, but like anything, when you practice it enough, you eventually get good at it. So churning out books for me became both quicker and easier.
(4) In your long career in computer science, you have worked on what might be called the "core" of the discipline: compilers, algorithms, programming languages, databases. What —or who— inspired you in your younger days to take on these foundational challenges? I ask this because we are living in an increasingly specialized world where the fundamentals are often overlooked.
In the early days of CS, there was very little content, and very few different kinds of software that were significant. Even databases were not really a thing until the mid-1970s. So you could pretty much know something about everything that was considered "computer science." Put another way, everything we had available as challenges was in an area we now consider "core."
(5) For decades, computer science has oscillated between the pursuit of formal foundations and the pressure for pragmatic solutions. How have you experienced that tension between theoretical elegance and practical usefulness? Do you think we are now closer to reconciling these two dimensions—or further apart?
I would say slightly closer. It's not that theory and practice have to be reconciled, but the leaders in many fields have recognized that theory has a role to play in developing useful software. In the early days, we really had no idea what sorts of theory would be useful, so people did pretty much anything they wanted and called it "CS theory." Ironically, it was the success of things like theory of parsing, where some sophisticated mathematics really did reduce the time it took to design and implement a parser from months to hours, that made people believe everything was going to yield to a theory. It took a while to realize that was false. Some things really are better because someone came up with the right abstraction or the right mathematical approach, but other things just don't seem to have a useful theory.
(6) Over the course of your career, you’ve tackled some of the most fundamental problems in computer science. What would you say has been the most technically challenging problem you’ve faced, and how did you go about solving it—both intellectually and practically?
Well I never had the patience to work on something for more than a week. But let me talk about the challenge that eventually was called "Datalog." Around 1983, I noticed that the AI community was dealing with data much like the database community was, but instead of using languages like SQL that were both tranctable (queries could be executed in polynomial time) and optimizable (SQL, at least its core, is sufficiently simple that you can tell if two queries were equivalent in what they did), AI was looking at more and more complex forms of logic that, while they could express more than SQL, were neither tractable nor optimizable. So I set out to propose a version of logic -- collections of first-order Horn clauses (if this and this and... then that), that could do the core of SQL, but also could do recursion, which the SQL of the day could not. This language, "Datalog," was also tractable and, as research later showed, pretty well optimizable.
But the big challenge was political, and extended over decades. AI folks didn't like it because it was too weak, and database people didn't like it because they saw no need for recursion. A form of recursion that was inspired by Datalog eventually found it into the SQL98 standard and is now implemented by major vendors. One of optimization algorithms that came out of the Datalog research -- "magic sets" -- was implemented, but in another, unexpected context, in IBM's SQL compiler before that. It was implemented at scale by LogicBlox, and it has been used in various unexpected ways, e.g., Joe Hellerstein's use in analysis of distributed systems, or Monica Lam's use in code optimization.
(7) I hope this doesn’t sound like a cliché, but it’s a question that sparks curiosity. What advice would you give to a young researcher who hopes to make meaningful contributions to computer science in this era of rapid change, where trends like AI and data-driven approaches often dominate the spotlight?
Here's one suggestion that few agree with, but in practice is pretty good. People assume the way you do research is you read everything in a field, and then tackle one of the open problems that you find at the end of some papers. I think that is a mistake for the following reason. Someone may see a real problem -- one that really needs a solution. They try to solve it, get somewhere, but don't really solve it. So they write a paper and at the end, they suggest someone complete the solution. Someone else reads that paper. They can't solve it either, but they really don't know the practical need the paper was addressing. To them it was just some abstract question. So they fiddle around with it, find something that is close to what the open problem is, but perhaps not really addressing the core problem, and they write a paper about it and throw out something they were unable to do as an "open problem." A third person, picks up that paper, has less understanding of the real problem, but solves a part of the "open problem" and poses something else as open. As this process continues, the papers get further and further away from the real problem, and people are just writing papers whose results are not really useful. The bottom line is "don't trust that a problem is worth solving just because someone else says it is "open."
What I used to tell my students is to read enough that you understand the terminology and basic abstractions or models that a field has, but then go off on your own. Pick a problem whose solution would be useful, and see if you can solve it. You then have to check the literature to make sure that what you have done is truly original. Occasionally, your search will uncover something that is uncomfortably close to what you have done, and you have to acknowledge that. I've seen effort lost because of that effect. But it is rare. More often, what you have is new. And because you started with a problem whose use you yourself identified, you know that what you have is worthwhile.
Lista de libros: http://infolab.stanford.edu/~ullman/ullman-books.html
La versión traducida se realizó usando Gemini 2.5 pro.