He estado pensando en esta pregunta por mucho tiempo, pero realmente no pude encontrar la respuesta en Google y una pregunta similar en Stackoverflow. Si hay un duplicado, lo siento.
Mucha gente parece decir que escribir compiladores y otras herramientas de lenguaje en lenguajes funcionales como OCaml y Haskell es mucho más eficiente y fácil que escribirlos en lenguajes imperativos.
¿Es esto cierto? Y si es así, ¿por qué es tan eficiente y fácil escribirlos en lenguajes funcionales en lugar de en un lenguaje imperativo, como C? Además, ¿una herramienta de lenguaje en un lenguaje funcional no es más lenta que en un lenguaje de bajo nivel como C?
Respuestas:
A menudo, un compilador trabaja mucho con árboles. El código fuente se analiza en un árbol de sintaxis. Ese árbol podría transformarse en otro árbol con anotaciones de tipo para realizar la verificación de tipos. Ahora puede convertir ese árbol en un árbol que solo contenga elementos básicos del lenguaje (convirtiendo notaciones sintácticas similares a azúcar en una forma sin azúcar). Ahora puede realizar varias optimizaciones que son básicamente transformaciones en el árbol. Después de eso, probablemente crearía un árbol en alguna forma normal y luego iteraría sobre ese árbol para crear el código de destino (ensamblaje).
El lenguaje funcional tiene características como la coincidencia de patrones y un buen soporte para la recursividad eficiente, lo que facilita el trabajo con árboles, por eso generalmente se consideran buenos lenguajes para escribir compiladores.
fuente
Muchas tareas del compilador coinciden con patrones en estructuras de árbol.
Tanto OCaml como Haskell tienen capacidades de coincidencia de patrones poderosas y concisas.
Es más difícil agregar coincidencia de patrones a lenguajes imperativos, ya que cualquier valor que se evalúe o extraiga para que coincida con el patrón debe estar libre de efectos secundarios.
fuente
Un factor importante a considerar es que una gran parte de cualquier proyecto de compilador es cuando puede auto-hospedar el compilador y "comer su propia comida para perros". Por esta razón, cuando observa lenguajes como OCaml, donde están diseñados para la investigación de lenguajes, tienden a tener excelentes características para problemas de tipo compilador.
En mi último trabajo de compilador, usamos OCaml exactamente por esta razón mientras manipulamos el código C, era la mejor herramienta para la tarea. Si la gente de INRIA hubiera construido OCaml con diferentes prioridades, podría no haber sido una buena opción.
Dicho esto, los lenguajes funcionales son la mejor herramienta para resolver cualquier problema, por lo que lógicamente se deduce que son la mejor herramienta para resolver este problema en particular. QED.
/ me: vuelve a mis tareas de Java con menos alegría ...
fuente
Básicamente, un compilador es una transformación de un conjunto de código a otro: de fuente a IR, de IR a IR optimizado, de IR a ensamblador, etc. Este es precisamente el tipo de cosas para las que están diseñados los lenguajes funcionales: una función pura es solo una transformación de una cosa a otra. Las funciones imperativas no tienen esta cualidad. Aunque puede escribir este tipo de código en un lenguaje imperativo, los lenguajes funcionales están especializados para ello.
fuente
Ver también
Patrón de diseño F #
FP agrupa cosas 'por operación', mientras que OO agrupa cosas 'por tipo', y 'por operación' es más natural para un compilador / intérprete.
fuente
Una posibilidad es que un compilador tiende a tener que tratar con mucho cuidado una gran cantidad de casos de esquina. Obtener el código correcto a menudo se facilita mediante el uso de patrones de diseño que estructuran la implementación de una manera que se asemeja a las reglas que implementa. A menudo, eso termina siendo un diseño declarativo (coincidencia de patrones, "dónde") en lugar de imperativo (secuenciación, "cuándo") y, por lo tanto, es más fácil de implementar en un lenguaje declarativo (y la mayoría de ellos son funcionales).
fuente
Parece que todos se perdieron otra razón importante. Es bastante fácil escribir un lenguaje específico de dominio integrado (EDSL) para analizadores que se parecen mucho a (E) BNF en código normal. Combinadores de analizador como Parsec son bastante fáciles de escribir en lenguajes funcionales utilizando funciones de orden superior y composición de funciones. No solo más fácil sino muy elegante.
Básicamente, usted representa los analizadores sintácticos genéricos más simples como solo funciones y tiene operaciones especiales (típicamente funciones de orden superior) que le permiten componer estos analizadores sintácticos primitivos en analizadores sintácticos más complicados y específicos para su gramática.
Por supuesto, esta no es la única forma de hacer marcos parer.
fuente