Uso de Process Calculi y PL Theory para el desarrollo moderno del lenguaje de programación


10

Desde hace un tiempo, he estado muy interesado en la teoría del lenguaje de programación y los cálculos de procesos y he comenzado a estudiarlos. Para ser honesto, es algo en lo que no me importaría entrar para una carrera. La teoría me parece increíblemente fascinante. Una pregunta constante con la que me encuentro constantemente es si PL Theory o Process Calculi tienen alguna importancia en el desarrollo moderno del lenguaje de programación. Veo muchas variantes en el cálculo Pi y hay mucha investigación activa, pero ¿alguna vez serán necesarias o tendrán aplicaciones importantes? La razón por la que pregunto es porque me encanta desarrollar lenguajes de programación y el verdadero objetivo final sería utilizar la teoría para construir realmente un PL. Para las cosas que he escrito, realmente no ha habido ninguna correlación con la teoría.

Respuestas:


9

Mi respuesta es realmente solo una elaboración de Gilles, que no había leído antes de escribir la mía. Tal vez, sin embargo, sea útil.

Permítanme comenzar mi intento de responder a su pregunta con una distinción entre dos dimensiones del trabajo de lenguajes de programación que se relacionan de manera muy diferente con la teoría del lenguaje de programación en general y el cálculo de procesos en particular.

  • Pura investigación.

  • Producto enfocado en investigación y desarrollo.

Este último generalmente tiene lugar en la industria con el objetivo de proporcionar lenguajes de programación como producto. Los equipos que desarrollan Java en Oracle y C # en Microsoft son ejemplos. Por el contrario, la investigación pura no está vinculada a los productos. Su objetivo es comprender los lenguajes de programación como objetos de interés intrínseco y explorar las estructuras matemáticas subyacentes a todos los lenguajes de programación.

Debido a objetivos divergentes, los diferentes aspectos de la teoría del lenguaje de programación son relevantes en la investigación pura y en la I + D centrada en el producto. La imagen a continuación puede indicar qué es importante dónde.

ingrese la descripción de la imagen aquí

En este punto, uno puede preguntarse por qué las dos dimensiones son tan diferentes y cómo se relacionan.

La idea clave es que la investigación y el desarrollo del lenguaje de programación tiene múltiples dimensiones: técnica, social y económica. Casi por definición, la industria está interesada en la rentabilidad económica de los lenguajes de programación. Microsoft y otros no desarrollan lenguajes por la bondad de sus corazones, sino porque creen que los lenguajes de programación les dan una ventaja económica. Y han investigado profundamente por qué algunos lenguajes de programación tienen éxito, y otros, aparentemente similares o con características más avanzadas, no lo hacen. Y descubrieron que no hay una sola razón. Los lenguajes de programación y sus entornos son complejos, y también lo son las razones para adoptar o ignorar cualquier lenguaje específico. Pero el factor más importante para el éxito de un lenguaje de programación es el apego preferencial de los programadores a los idiomas que ya se usan ampliamente: mientras más personas usan un lenguaje, más bibliotecas, herramientas, material didáctico están disponibles y más productivo es un programador. puede estar usando ese lenguaje. Esto también se llama efecto de red. Otra razón es el alto costo de cambiar idiomas para individuos y organizaciones: dominar el lenguaje, especialmente para un programador no tan experimentado, y cuando la distancia semántica a los idiomas familiares es grande, es un esfuerzo serio que lleva mucho tiempo. Teniendo en cuenta estos hechos, uno puede preguntarse ¿por qué los nuevos idiomas obtienen tracción? ¿Por qué las empresas desarrollan nuevos idiomas? ¿Por qué no nos quedamos con Java o Cobol? Creo que hay varias razones clave para que un idioma tenga éxito,

  • Se abre un nuevo dominio de programación que no tiene titulares que desplazar. El ejemplo principal es la web con su aumento concomitante de Javascript.

  • Lenguaje pegajoso. Con esto quiero decir el alto precio de cambiar el idioma. Pero a veces los programadores se trasladan a diferentes campos, toman un lenguaje de programación con ellos y tienen éxito con el lenguaje antiguo en el nuevo campo.

  • Un lenguaje es impulsado por una gran empresa con gran poder de fuego financiero. Este respaldo reduce el riesgo de adopción, porque los primeros usuarios pueden estar razonablemente seguros de que el lenguaje seguirá siendo compatible en unos pocos años. Un buen ejemplo de esto es C #.

  • Un lenguaje puede venir con herramientas convincentes y un ecosistema. Aquí también se podría mencionar C # y su ecosistema .Net y Visual Studio como ejemplo.

  • Los idiomas antiguos recogen nuevas características. Me viene a la mente Java, que, en cada iteración, recoge más buenas ideas de la tradición de la programación funcional.

  • Finalmente, un nuevo lenguaje podría tener ventajas técnicas intrínsecas, por ejemplo, ser más expresivo, tener una sintaxis más agradable, sistemas de tipeo que detecten más errores, etc.

Teniendo en cuenta estos antecedentes, no debería sorprendernos que haya una cierta desconexión entre la investigación del lenguaje de programación puro y el desarrollo del lenguaje de programación comercial. Si bien ambos tienen como objetivo hacer que la construcción y la evolución del software sean más eficientes, especialmente para el software a gran escala, el trabajo del lenguaje de programación industrial debe estar más interesado en facilitar la adopción rápida para alcanzar una masa crítica y obtener el efecto de red. Esto lleva a un enfoque de investigación en cosas que les interesan a los programadores que trabajan. Y eso tiende a ser cosas como la disponibilidad de la biblioteca, la velocidad del compilador, la calidad del código compilado, la portabilidad, etc. El cálculo del proceso tal como lo practicamos hoy es de poca utilidad para los programadores que trabajan en proyectos convencionales (aunque creo que eso cambiará en el futuro).

La investigación pura del lenguaje de programación es bastante diferente. Funciona con modelos simplificados de lenguajes de programación: el cálculo es una simplificación masiva de la programación funcional. Del mismo modo, -calculus es una simplificación masiva de la programación concurrente. Estas simplificaciones masivas son la clave para una investigación exitosa. Nos permiten centrarnos en los mecanismos informáticos centrales (por ejemplo,π βλπβ-reducción para programación funcional, resolución / unificación para programación lógica, paso de nombres para computación concurrente). Para entender si un lenguaje como Scala puede tener una inferencia de tipos completa viable, no debemos preocuparnos por la JVM. De hecho, pensar en la JVM le restará una mejor comprensión de la inferencia de tipos. Es por eso que la abstracción de la computación en pequeños cálculos centrales es vital y poderosa.

Por lo tanto, puede pensar en la investigación del lenguaje de programación como una caja de arena masiva donde las personas juegan con juguetes, y si encuentran algo interesante cuando juegan con un juguete específico y lo han investigado a fondo, ese juguete interesante comienza su larga marcha hacia la aceptación industrial convencional . Digo una larga marcha porque las características del lenguaje inventadas por primera vez por el investigador del lenguaje de programación tienden a tomar décadas antes de ser ampliamente aceptadas. Por ejemplo, la recolección de basura se concibió en la década de 1950 y se hizo ampliamente disponible con Java en la década de 1990. La coincidencia de patrones se remonta a 1970 y se usa ampliamente solo desde Scala.

El cálculo del proceso es un juguete especialmente interesante. Pero es demasiado nuevo para ser investigado a fondo. Eso tomará otra década de investigación pura. Lo que actualmente está en la investigación de la teoría de procesos es tomar la historia de éxito más grande de la investigación del lenguaje de programación, la teoría de los tipos (secuenciales) y desarrollar la teoría de los tipos para la concurrencia de mensajes. Los sistemas de mecanografía de expresividad moderada para la programación secuencial, dicen Hindley-Milner, ahora son bien entendidos, ubicuos y aceptados por los programadores que trabajan. Nos gustaría tener tipos moderadamente expresivos para la programación concurrente. La investigación sobre esto comenzó en la década de 1980 por pioneros como Milner, Sangiorgi, Turner, Kobayashi, Honda y otros, a menudo basados, explícita o implícitamente, en la idea de linealidad que proviene de la lógica lineal. Los últimos años han visto un aumento importante en la actividad y espero que esta trayectoria ascendente continúe en el futuro previsible. También espero que este trabajo comience a filtrarse hacia la I + D centrada en el producto, en parte por la razón pragmática de que los jóvenes investigadores que han sido capacitados en cálculo de procesos irán y trabajarán en laboratorios industriales de I + D, pero también debido a la evolución de la arquitectura de la CPU y la computadora. de formas secuenciales de computación.

En resumen, no me preocuparía que no encuentre útil la teoría del lenguaje de programación de vanguardia, como el cálculo de procesos, en su propio trabajo de construcción de lenguajes. Eso es simplemente porque la teoría de vanguardia no aborda las preocupaciones de los lenguajes de programación actuales. Se trata de futuros idiomas. Tomará un tiempo para que el 'mundo real' se ponga al día. El conocimiento que usa para construir lenguajes para hoy es la teoría del lenguaje de programación del pasado. Te animo a que aprendas más sobre el cálculo de procesos porque es una de las áreas más emocionantes de toda la informática teórica.


1
¡Guauu! ¿Cuánto tiempo me llevó hacer ese diagrama y puedo usarlo en el futuro?
cody

1
@cody Tardó unos segundos con OmniGraffle y siéntase libre de usarlo.
Martin Berger

8

La ciencia del diseño del lenguaje de programación está en su infancia. La teoría (el estudio de lo que significan los programas y la expresividad de un lenguaje) y el empirismo (lo que los programadores logran o no logran hacer) brindan muchos argumentos cualitativos para sopesar de una forma u otra al diseñar un lenguaje. Pero rara vez tenemos una razón cuantitativa para decidir.

Hay una demora entre el momento en que alguna teoría se estabiliza lo suficiente como para que una innovación sea utilizable en un lenguaje de programación práctico, y el momento en que esta innovación comienza a aparecer en lenguajes "convencionales". Por ejemplo, se puede decir que la administración automática de memoria con recolección de basura maduró para uso industrial a mediados de la década de 1960, pero que solo alcanzó la corriente principal con Java en 1995. El polimorfismo paramétrico se entendió bien a fines de la década de 1970, y lo logró en Java a mediados de los años 200. En la escala de la carrera de un investigador, 30 años es mucho tiempo.

La adopción industrial a gran escala de un lenguaje es una cuestión que deben estudiar los sociólogos, y esa ciencia está aún más en pañales. Las consideraciones del mercado son un factor importante: si Sun, Microsoft o Apple aprueban un idioma, esto tiene mucho más impacto que cualquier número de documentos POPL y PLDI. Incluso para un programador que tiene una opción, la disponibilidad de la biblioteca suele ser mucho más importante que el diseño del lenguaje. Lo que no quiere decir que el diseño del lenguaje no sea importante: ¡tener un lenguaje bien diseñado es un alivio! Por lo general, no es el factor decisivo.

Los cálculos de proceso todavía están en la etapa en que la teoría no se ha estabilizado. Creemos que entendemos los cálculos secuenciales: todos los modelos de cosas que nos gusta llamar cálculo secuencial son equivalentes (esa es la tesis de Church-Turing). Esto no es válido para la concurrencia: los cálculos de procesos diferentes tienden a tener diferencias sutiles en la expresividad.

Los cálculos de proceso tienen implicaciones prácticas. Se distribuyen muchos cálculos: involucran clientes que hablan con servidores, servidores que hablan con otros servidores, etc. Incluso los cálculos locales a menudo son multiproceso para aprovechar el paralelismo sobre múltiples procesadores y reaccionar a la concurrencia ambiental (comunicación con programas independientes). y con el usuario).

¿Se necesitan avances de investigación para hacer un mejor software? Después de todo, hay una industria de mil millones de dólares que no puede distinguir el cálculo pi de un pastel en el cielo. Por otra parte, esa industria gasta miles de millones de dólares reparando errores.

"¿Alguna vez serán necesarios" nunca es una pregunta que valga la pena en la investigación. Es imposible predecir de antemano qué tendrá consecuencias a largo plazo. Incluso iría más lejos y diría que es una suposición segura que cualquier investigación tendrá consecuencias algún día, simplemente no sabemos en ese momento si ese día llegará el próximo año o el próximo milenio.


3

Veo muchas variantes en el cálculo Pi y hay mucha investigación activa, pero ¿alguna vez serán necesarias o tendrán aplicaciones importantes?

La razón por la que pregunto es porque me encanta desarrollar lenguajes de programación y el verdadero objetivo final sería utilizar la teoría para construir realmente un PL. Para las cosas que he escrito, realmente no ha habido ninguna correlación con la teoría.

Esta es una pregunta difícil! Te diré mi opinión personal, y enfatizo que esta es mi opinión .

No creo que el cálculo pi sea directamente adecuado como una notación para la programación concurrente. Sin embargo, creo que definitivamente deberías estudiarlo antes de diseñar un lenguaje de programación concurrente. La razón es que el cálculo pi da un nivel bajo --- pero lo más importante, ¡composicional! --- cuenta de concurrencia. Como resultado, puede expresar todo lo que desee, pero no siempre convenientemente.

Explicar este comentario requiere pensar un poco sobre los tipos. Primero, los lenguajes de programación útiles generalmente necesitan algún tipo de disciplina de tipo para construir abstracciones. En particular, necesita algún tipo de tipo de función para hacer uso de abstracciones de procedimiento al crear software.

Ahora, la disciplina de tipo natural del cálculo pi es una variante de la lógica lineal clásica. Ver, por ejemplo, el documento Process Realizability de Abramsky , que muestra cómo interpretas los programas concurrentes simples como pruebas de proposiciones de la lógica lineal. (La literatura contiene mucho trabajo sobre tipos de sesión para escribir programas de cálculo pi, pero los tipos de sesión y los tipos lineales están muy relacionados).

Sin embargo, dije que la disciplina de tipo natural del cálculo pi es la lógica lineal clásica , y esta es la fuente de la dificultad de usarla directamente como lenguaje de programación. En la mayoría de las presentaciones de lógica lineal clásica, la función (lineal) tipo no es primitiva. En su lugar, se codifica utilizando los tipos de función de Morgan dualidad .ABAB

Esto está bien desde la teoría del tipo POV, pero es incómodo cuando se programa. La razón es que los programadores terminan administrando no solo sus llamadas a funciones, sino también la pila de llamadas. (De hecho, las codificaciones de cálculo lambda en cálculo pi generalmente terminan pareciéndose a transformaciones de CPS). Ahora, escribir asegura que nunca estropearán esto, pero sin embargo es una gran cantidad de contabilidad impuesta al programador.

Este no es un problema exclusivo de la teoría de la concurrencia: el cálculo mu proporciona una buena explicación teórica de los operadores de control secuencial como call / cc, pero al precio de hacer explícita la pila, lo que lo convierte en un lenguaje de programación incómodo.

Entonces, al diseñar un lenguaje de programación concurrente, mi opinión es que debe diseñar su lenguaje con abstracciones de nivel superior que el cálculo pi sin procesar, pero debe asegurarse de que se traduzca limpiamente en un cálculo de proceso mecanografiado sensible. (Un buen ejemplo reciente de esto es los procesos, funciones y sesiones de orden superior de Tonhino, Caires y Pfenning : una integración monádica ).


¿En qué sentido necesita administrar la pila de llamadas en -calculus? Esto sucede automáticamente en la codificación de en Milner y también en la nueva codificación Van Bakel / Vigliotti. Las funciones son una forma perfectamente fina de azúcar sintáctica en cálculo. πλππ
Martin Berger

Además, el cálculo es una cuenta realmente incómoda de operadores de control secuencial como call / cc. Tales operadores se expresan mucho más fácil y naturalmente en -caluclus, porque saltar es claramente una forma de pasar mensajes. -calculus no tiene una noción natural de nombre a la que pueda saltar, por lo que debe codificarlo como aplicación de función, o debe agregar cosas adicionales. λμπλ
Martin Berger

Una forma fructífera de pensar acerca de las funciones es que son interacciones cliente-servidor, donde el canal de retorno es afín y el canal del servidor se replica. Esto se puede escribir fácilmente. Los tipos de sesión no capturan completamente esto, ya que son un poco demasiado débiles en las restricciones de interacción que imponen.
Martin Berger

Dicho todo esto, por supuesto, uno no quiere programar en raw -calculus más que en raw -calculus. Ambos formalismos son simplificaciones que nos permiten centrarnos en algunas características de la computación, excluyendo otras. πλ
Martin Berger

@ MartinBerger: ¡Esperaba convencerte de que contestaras! Quiero decir que si quisieras programar en raw , y también quisieras usar funciones, terminarías escribiendo términos que están en la imagen de la traducción de Milner, y entonces tendrías que "administrar la pila" en el sentido de que esencialmente estarías administrando continuaciones y sustituciones explícitas. (Como comentario, no sabía sobre el artículo de Van Bakel / Vigliotti, ¡gracias!)π
Neel Krishnaswami

1

Usted dice que "el verdadero objetivo final sería utilizar la teoría para construir realmente un PL". Entonces, ¿presumiblemente admites que hay otros objetivos?

Desde mi punto de vista, el propósito número 1 de la teoría es proporcionar comprensión, que puede ser razonar sobre los lenguajes de programación existentes, así como los programas escritos en ellos. En mi tiempo libre, mantengo una gran pieza de software, un cliente de correo electrónico, escrito hace años en Lisp. Toda la teoría PL que conozco, como la lógica de Hoare, la lógica de separación, la abstracción de datos, la parametridad relacional y la equivalencia contextual, etc., es útil en el trabajo diario. Por ejemplo, si estoy ampliando el software con una nueva característica, sé que todavía tiene que preservar la funcionalidad original, lo que significa que debe comportarse de la misma manera en todos los contextos antiguos a pesar de que va a hacer algo nuevo en nuevos contextos Si no supiera nada sobre equivalencia contextual, probablemente ni siquiera podría enmarcar el problema de esa manera.

En cuanto a su pregunta sobre el cálculo de pi, creo que el cálculo de pi todavía es un poco nuevo para encontrar aplicaciones en el diseño del lenguaje. La página de Wikipedia en pi-calculus menciona BPML y occam-pi como diseños de lenguaje que usan pi-calculus. Pero también puede mirar las páginas de su predecesor CCS, y otros cálculos de procesos como CSP, unir cálculos y otros, que se han utilizado en muchos diseños de lenguaje de programación. También puede consultar la sección "Objetos y cálculo pi" del libro de Sangiorgi y Walker para ver cómo se relaciona el cálculo pi con los lenguajes de programación existentes.


0

Me gusta buscar implementaciones prácticas de cálculos de procesos en la naturaleza :) (además de leer sobre la teoría).

  1. Los canales asíncronos de Clojure se basan en CSP: http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
  2. Golang también tiene canales basados ​​en CSP (creo que esto inspiró a Rich Hickey para clojure): http://www.informit.com/articles/printerfriendly/1768317
  3. Hay un tipo que hizo una extensión basada en ACP para scala (Subíndice) pero no tengo suficiente reputación para publicar el enlace ...

etc.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.