¿Qué son las funciones por etapas (conceptualmente)?

24

En un artículo reciente de CACM [1], los autores presentan una implementación para funciones por etapas . Usan el término como si fuera bien conocido, y ninguna de las referencias parece una introducción obvia.

Dan una breve explicación (el énfasis es mío y el número de referencia cambió; es 22 en el original)

En el contexto de la generación de programas, la programación multietapa (MSP, puesta en escena para abreviar) establecida por Taha y Sheard [2] permite a los programadores retrasar explícitamente la evaluación de una expresión de programa a una etapa posterior (por lo tanto, poner en escena una expresión). La etapa actual actúa efectivamente como un generador de código que compone (y posiblemente ejecuta) el programa de la siguiente etapa.

Sin embargo, Taha y Sheard escriben (el énfasis es mío):

Un programa de etapas múltiples es aquel que involucra la generación, compilación y ejecución de código, todo dentro del mismo proceso. Los lenguajes de etapas múltiples expresan programas de etapas múltiples. La puesta en escena y, en consecuencia, la programación en varias etapas, abordan la necesidad de soluciones de uso general que no paguen gastos generales de interpretación en tiempo de ejecución.

Luego van a varias referencias a trabajos más antiguos que supuestamente muestran que la puesta en escena es efectiva, lo que sugiere que el concepto es aún más antiguo. No dan una referencia para el término en sí.

Estas declaraciones parecen ser ortogonales, si no contradictorias; tal vez lo que escriben Rompf y Odersky es una aplicación de lo que proponen Taha y Sheard, pero tal vez sea otra perspectiva sobre lo mismo. Parecen estar de acuerdo en que un punto importante es que los programas (re) escriben partes de sí mismos en tiempo de ejecución, pero no sé si esa es una habilidad necesaria o suficiente.

Entonces, ¿qué es la puesta en escena, respectivamente, son interpretaciones de puesta en escena en este contexto? ¿De dónde viene el término?


  1. Puesta en escena modular ligera: un enfoque pragmático para la generación de código de tiempo de ejecución y DSL compilados por T. Rompf y M. Odersky (2012)
  2. MetaML y programación de etapas múltiples con anotaciones explícitas de W. Taha y T. Sheard (2000)
Rafael
fuente
¿Qué contradicción ves entre las dos declaraciones? Para mí, parece que están hablando de lo mismo, con diferente énfasis.
Gilles 'SO- deja de ser malvado'
@Gilles No necesito la generación / compilación de código de tiempo de ejecución para retrasar la evaluación de algo (ver continuables). Es muy posible que sea solo otro énfasis (admito esa opción en la pregunta), pero realmente no puedo decirlo.
Raphael
Puede consultar la implementación del lenguaje de programación Julia y la documentación de metaprogramación en @generated functions: julia.readthedocs.org/en/latest/manual/metaprogramming/…
SalchiPapa

Respuestas:

21

Que yo sepa, el término computación por etapas fue utilizado por primera vez por Bill Scherlis en este documento . Antes de eso, el término " evaluación parcial " se usaba para el mismo concepto, pero la idea del cálculo por etapas es sutilmente diferente. Ambas ideas están relacionadas con el teorema Smn de Kleene .

Si tiene una función de dos argumentos, pero conoce un argumento, digamos , entonces puede realizar parte del cálculo de la función de inmediato utilizando el conocimiento del primer argumento. Lo que queda es una función cuyos cálculos solo dependen del segundo argumento desconocido.m ϕ m ( n )ϕ(m,n)mϕm(n)

La idea de la evaluación parcial es calcular la función especializada automáticamente . Dado el código para la función original , la evaluación parcial realiza un análisis estático para determinar qué bits del código dependen de cuáles bits dependen de , y lo transforma en una función que, dado , construyeϕm(n) m n ϕ m ϕ mϕmnϕmϕmn

ϕmϕmϕm

ϕϕ

  • ¿Cómo definir funciones escalonadas?
  • ¿Qué lenguajes de programación y sistemas de tipos deberían usarse para definir funciones por etapas?
  • ¿Cuál es la semántica de tales lenguajes?
  • ¿Cómo aseguramos la coherencia y corrección de las funciones por etapas?
  • ¿Qué técnicas son útiles para la construcción automática o semiautomática de funciones por etapas?
  • ¿Cómo demostramos la exactitud de tales técnicas?

La computación por etapas puede ser muy importante en la práctica. De hecho, cada compilador es, en efecto, un cálculo por etapas. Dado un programa fuente, construye un programa objetivo traducido y optimizado, que luego puede tomar la entrada real y calcular el resultado. Es difícil escribir programas de computación por etapas en la práctica porque tenemos que hacer malabarismos con las múltiples etapas y asegurarnos de que se hagan las cosas correctas en el momento adecuado. Todos los que han escrito un compilador han tenido problemas con tales problemas. También es difícil escribir programas que escriban otros programas, ya sean programas de lenguaje de máquina (compiladores), consultas SQL (manipulaciones de bases de datos) o código HTML / Páginas de servidor / Javascript (aplicaciones web) y una miríada de otras aplicaciones.

Uday Reddy
fuente
ϕϕ
Entonces, lo que quiere decir es que la evaluación parcial es una abstracción sobre la programación de etapas múltiples, lo que significa que la evaluación parcial no implica programación de etapas múltiples, pero la programación de etapas múltiples implica evaluación parcial. Por lo que la evaluación parcial se puede hacer en una o varias etapas, ya que cursar en lenguajes funcionales no implica necesariamente múltiples etapas y generar código en tiempo de ejecución, ¿verdad?
denis631
1
No exactamente. Un evaluador parcial compila un programa ordinario en un programa de 2 etapas y luego ejecuta su primera etapa. En la programación por etapas, usted mismo escribe el programa de etapas múltiples.
Uday Reddy
9

Aunque las otras respuestas son técnicamente correctas, no creo que den una comprensión correcta de por qué los científicos informáticos están interesados ​​en funciones organizadas.

Al crear funciones por etapas, usted define programas que generan programas. Uno de los grandes objetivos de la teoría moderna del lenguaje práctico es maximizar la reutilización potencial. Queremos que sea posible escribir bibliotecas que no sean solo funciones y objetos útiles, sino que ayuden a los programadores al proporcionar construcciones arquitectónicas de orden superior.

Sería genial si pudiéramos deshacernos de todo el código repetitivo. Deberíamos poder minimizar el lenguaje de especificación. Si queremos un despachador controlado por eventos, por ejemplo, que se comunique con otros despachadores con un diseño de subproceso determinado, deberíamos poder especificarlo de forma compacta, y todos los escuchas de E / S y las conexiones de subproceso y objeto de cola deberían poder construirse a partir de esa especificación.

Los lenguajes de dominio tienden a ser esas representaciones compactas que estamos buscando. Cuando las personas trabajan en un dominio durante un tiempo, el lenguaje que utilizan tiende a eliminar la mayor parte de la duplicación de información y convertirse en una especificación simplificada. Entonces, esta teoría de la puesta en escena tiende a convertirse en un sistema de traducción de los idiomas de dominio al lenguaje de ejecución.

Los compiladores son técnicamente etapas, pero se pierde el objetivo. El objetivo de la puesta en escena moderna es permitir la creación de programas que creen programas para maximizar la reutilización y automatizar la construcción de programas siempre que sea posible. Sería genial si algún día los requisitos funcionales de un programa fueran el programa.

Ver "Programación Generativa" por Czarnecki y Eisenecker (ISBN-13: 978-0201309775).

ex0du5
fuente
@Raphael: Aquí está el capítulo tres con los conceptos básicos sobre dominios y reutilización. Mira incluso la optimización que mencionas. FFT no se realiza por etapas para que funcione más rápido. Se hace para que el programador no tenga que calcular la tabla de valores cada vez a mano, copiarlos en el programa y construir una gran lista. Es para minimizar el trabajo realizado y reutilizar los pasos básicos. Lo mismo con el ciclo de desenrollado. Hacerlo a mano repite la información y no se puede reutilizar.
ex0du5
Este punto de vista DSL parece limitar la puesta en escena a un nivel (un compilador DSL dentro del programa), ¿verdad?
Raphael
1
@Raphael: Realmente depende de tu punto de vista. Obviamente, el concepto no agrega poder computacional cuando se ve simplemente como la fuente -> traducción ejecutable. Podríamos construir un compilador para el lenguaje DS y listo. De dónde viene su fuerza es en la iteración. Al construir bibliotecas que serán utilizadas y expandidas por proyectos en el futuro, las etapas naturales aparecen dentro de los límites de la biblioteca. Es posible que tenga una biblioteca que se transforma en objeto especificaciones fuente de serialización completa, y luego otra biblioteca que se construye la capa de transporte construida sobre algunas especificaciones de despacho ...
ex0du5
1
@Raphael: la puesta en escena puede realizarse de forma más natural con múltiples etapas. Si una parte del código ha tenido que sus requisitos cambien mucho con el tiempo, donde otros son mucho más estables, puede ser apropiado debido a las "capas de corte" para separar la puesta en capas en interfaces con interfaces más estables. Luego puede afectar menos el sistema con cambios y respetar una forma de puesta en escena del principio abierto-cerrado. Esas son preocupaciones prácticas que no tienen necesidad matemática, pero todo se basa en la practicidad. No queremos un solo lenguaje de compilación, queremos permitir la evolución.
ex0du5
5

La respuesta se da en la pieza de perspectiva técnica para el artículo en cuestión [1]. El problema en consideración es el área de tensión entre el código general y el específico:

Los programas pueden redactarse para fines generales o especiales. El código de propósito general tiene la ventaja de ser utilizable en una variedad de situaciones, mientras que el código de propósito especial podría escribirse de una manera que aproveche las características únicas del entorno de ejecución y, por lo tanto, gane eficiencia a costa de la reutilización.

Por supuesto, queremos resolver esta tensión, es decir, lograr un código general y una implementación específica:

Podemos hacer la pregunta: ¿es posible escribir código para que sea de uso general pero luego hacer que se especialice automáticamente en la situación en cuestión durante la ejecución?

Esto ha dado lugar a la idea de que los programas (generales) (re) se escriban en tiempo de ejecución para adaptarse a una situación específica:

Como resultado, una dirección importante de investigación ha involucrado la búsqueda de lenguaje y tecnología de compilación que permita a los programadores escribir código de propósito general que luego se convierte de manera correcta y eficiente en código especializado de alto rendimiento en tiempo de ejecución.

Supongo que el JIT de Java es un buen ejemplo. Una idea particular es la programación de etapas múltiples, que Lee explica así:

En esta línea de investigación, una de las ideas centrales es el concepto de puesta en escena. Imaginamos que la ejecución de un programa se desarrolla en una serie de etapas, cada una calculando los valores que utilizan las etapas posteriores. Lo que buscamos, entonces, es escribir el código del programa para que de alguna manera estas etapas se hagan evidentes. Si esto se logra, entonces podemos hacer arreglos para que el código de la etapa posterior se compile en generadores de código que optimicen los resultados de los cálculos de la etapa anterior.

Es decir, la "puesta en escena" es una forma de ver las funciones / códigos adecuados que identifican fases en el cálculo / ejecución que pueden simplificarse conociendo los resultados de fases anteriores. El cálculo "demorado" como en la primera cita de la pregunta puede ser un efecto secundario necesario para separar las etapas correctamente, pero no es el punto.

Rompf y Odersky mencionan la transformación rápida de Fourier como un ejemplo que puede ser instructivo.


  1. El zorro y el erizo: perspectiva técnica de Peter Lee (2012)
Rafael
fuente