Un bucle Lectura-Evaluación-Impresión, REPL por las siglas en inglés de «Read-Eval-Print-Loop», también conocido como alto nivel interactivo o consola de lenguaje, es un entorno de programación interactiva basado en un proceso cíclico donde se lee un fragmento de código ingresado por el usuario, se evalúa y se devuelve un resultado al usuario; las partes de programa escrito en un entorno pueden compartir un estado global mientras el programa esté activo. El término se utiliza normalmente para referirse a interfaces de programación similares al clásico entorno interactivo de programación de la máquina Lisp. Entre los ejemplos comunes se cuentan las interfaces de línea de comandos y entornos similares de lenguajes de programación. Es especialmente característico de los lenguajes de script.[1]
En un REPL, el usuario introduce una expresión, REPL evalúa y muestra el resultado. El nombre «bucle lectura-evaluación-impresión» viene de los nombres de las funciones primitivas de Lisp las cuales implementan esta funcionalidad:
(+ 1 2 3)
, la cual es parseada en una lista vinculada que contiene cuatro elementos de información.+
es llamada con los argumentos 1 2 3
, generando el resultado 6
.6
no necesita mucho formateo para ser mostrado.El entorno de desarrollo, entonces, retorna al estado de lectura, creando un bucle, que termina cuando se cierra el programa.
La utilización de este tipo de entornos facilita la programación explorativa y la depuración, puesto que el programador puede inspeccionar el resultado mostrado antes de decidir qué expresión aportar para la siguiente lectura. El bucle lectura-evaluación-escritura involucra al programador más frecuentemente que el clásico ciclo editar-compilar-ejecutar-depurar.
Puesto que la función print
devuelve la información en el mismo formato textual que el utilizado en la función read
de entrada de datos, muchos resultado son mostrados en un formato permite, si ello fuera útil, ser copiado y pegado de nuevo hacia el REPL. Sin embargo, a veces es necesario imprimir representaciones de elementos que pueden no ser fácilmente leídos de nuevo, como una gestión de un socket o una compleja instancia de una clase. En estos casos, debe existir una sintaxis para objetos no legibles. En Python, se trata de la notación <__module__.class instance>
y en Common Lisp, la figura #<loquesea>
. El REPL de CLIM, SLIME y la máquina Lisp pueden también leer de nuevo objetos no legibles. Estos almacenan para cada output qué objeto ha sido mostrado. Después cuando el código es leído de vuelta, el objeto será recuperado desde el output mostrado.
Se pueden crear REPLs compatibles con cualquier lenguaje basado en texto. El soporte de REPL para lenguajes de compilador es comúnmente realizado implementando un intérprete sobre una máquina virtual que provee una interfaz al compilador. Ejemplos de REPLs para lenguajes de compilador serían CINT ─y su sucesor Cling─, ch y BeanShell.
Prácticamente todas las consolas UNIX son REPLs para lenguajes de Turing completo. Como una consola, un entorno REPL permite a los usuarios acceder a características relevantes de un sistema operativo además de proveer acceso a funcionalidades de programación.
El uso más extendido para los REPLs fuera de las consolas de sistemas operativos es para prototipado de software instantáneo. Otro usos incluyen cálculo matemático, creación de documentos que integran análisis científico (por ejemplo IPython), mantenimiento de software interactivo, benchmarking y exploración de algoritmos
Un REPL puede convertirse en una parte esencial del aprendizaje de un nuevo lenguaje ya que provee un retroestímulo para el aprendiz.
Para implementar un REPL en Lisp, es necesario únicamente implementar estas tres funciones y una función de bucle infinito (obviamente, la implementación de eval será complicada, dado que se debe también implementar todas las funciones primitivas como car o + y operadores especiales como if.). Hecho esto, un REPL básico es una única línea de código:
(loop (print (eval (read))))
Una posible implementación de eval es un intérprete recursivo que actúa sobre el árbol de sintaxis abstracta creado por read. Otra posibilidad es compilar el árbol de sintaxis en código máquina y ejecutarlo.
Las implementaciones reales de REPLs en Lisp son en ocasiones mucho más complicadas.
Funcionalidades típicas provistas por un REPL Lisp incluyen: