5

Tengo una pregunta general acerca de los intérpretes de lenguajes funcionales:¿Tiene tiempo de ejecución suelen utilizar una interpretación imperativo similar de código de lenguaje funcional

¿Hay realmente alguna ventaja en el uso de un lenguaje funcional en comparación con un lenguaje imperativo en tiempo de ejecución (o que hacer su camino hacia el intérprete)?

Ninguna de las preguntas que vi (como this) realmente captan esta pregunta, y las búsquedas se inundan de argumentos sobre las definiciones de diferentes idiomas.

EDIT: reducido a la única pregunta que terminé necesitando respuesta.

+2

¿Qué quiere decir con ventajas que se abren camino hacia el intérprete? – sepp2k

+1

@ sepp2k Al igual que los ejemplos específicos que enumeré: parece haber varias características comunes de los lenguajes de programación funcionales. Quiero saber si estas características que parecen diferenciar la programación funcional del estilo imperativo realmente marcarán alguna diferencia en el tiempo de ejecución, o es solo una diferencia más superficial en el estilo de codificación que diferencia a los dos. ¿Tener sentido? –

+0

Cambié el título y un poco de la pregunta, espero que esté más claro ahora. –

Respuesta

29

La respuesta corta es: todo se compila al final en un lenguaje de bajo nivel (ensamblado o lenguaje de máquina virtual). Los lenguajes funcionales e imperativos están en pie de igualdad: tienen que compilar sus mecanismos de abstracción para adaptarse a lo que está disponible en la máquina.
Donde el idioma marca la diferencia es qué tan cerca coinciden con el código subyacente de bajo nivel (proporcionando características de bajo nivel para optimizar el código a mano cuando sea conveniente) y qué optimizaciones permiten o facilitan teniendo una semántica limpia que proporciona fuertes garantías de razonamiento .

Por ejemplo, cuando se compila con código nativo, la recursión no se compila (en general) en bucles, sino en saltos a etiquetas, como lo hacen los bucles: la mayoría de los lenguajes ensamblados no tienen bucles ni recursión. Por supuesto, si compila en una máquina virtual que tiene bucles pero no salta, necesita producir bucles; esto es un problema, por ejemplo, en la Máquina Virtual de Java, porque las llamadas de cola generales son más expresivas que los bucles solos y debe evitar esa limitación, renunciando a cierta eficiencia.

Las "ventajas" de los programas funcionales pueden ser que debido a que la semántica se comporta mejor, puede razonar más fácilmente sobre el programa y, por ejemplo, expresar optimizaciones de una manera más simple. Actualmente, muchos compiladores usan el formulario intermedio Single Static Assignment (SSA), que es básicamente un lenguaje funcional de bajo nivel¹, aunque fue descubierto de forma independiente por personas de la comunidad del compilador. La mayoría de las optimizaciones son más fáciles de hacer cuando se han eliminado las mutaciones variables, por ejemplo, y una variable mantiene el mismo valor en todo su alcance. Existen algunas técnicas para registrar la asignación en more efficient ways en dichas formas intermedias funcionales.

¹: Vea el artículo corto 1998 de Andrew Appel: SSA is Functional Programming; Si está interesado en detalles sobre el formulario de SSA, aquí están some reading notes sobre la relación entre SSA y otras formas intermedias funcionales, como CPS.

También puede obtener ventajas de optimización a partir de la pureza (la ausencia de efectos secundarios, o al menos un buen control en el que el cálculo será libre de efectos secundarios) y el tipado estático. De la pureza puede derivar optimizaciones potentes como deforestation o fusion (eliminando las estructuras de datos intermedias), y al escribir puede obtener fuertes garantías sobre la forma de sus valores (es por eso que algunos lenguajes dinámicos intentan permitir algunas anotaciones de tipo restringido para la optimización fines) que permiten generar un mejor código.

En lo que respecta al acceso a las características de bajo nivel: Fortran, C y C++ son probablemente los mejores, y más ampliamente disponibles, "pueden ir a muy bajo nivel".Algunos lenguajes intentan proporcionar algunas de esas capacidades: por ejemplo ATS (originalmente un lenguaje de programación funcional, aunque es tan simple que es bastante difícil de ver) proporciona un buen control en la asignación de pila asignación-pila-asignación, ambos Haskell y the CLR (C#,etc.) proporcionan unboxed los tipos compuestos como un caso especial de dicho razonamiento de bajo nivel, y de manera similar, Rust está tratando de proporcionarle formas de tomar decisiones de bajo nivel sobre el consumo de memoria.
Sin embargo, aunque esto es ciertamente útil cuando se ha aislado una pequeña sección de código que es crítica para sus actuaciones, y se desea optimizar al máximo (renunciando a cierta flexibilidad/simplicidad/mantenibilidad), esto no cambiará su vida en situaciones cotidianas, a menos que sea un programador incrustado/kernel. Probablemente obtendrá un mayor rendimiento general de un lenguaje productivo que le permite usar el nivel de abstracción correcto y dedicar más tiempo a elegir el diseño correcto y los algoritmos para su problema. Por supuesto, uno podría querer tener ambos, y es posible pero difícil.

+0

Esto es perfecto, gracias. –

0

¿Hay alguna ventaja en el uso de un lenguaje funcional frente a un lenguaje imperativo en el tiempo de ejecución (o que llegan al intérprete)?

Sí. Si usa un lenguaje funcional, la ventaja es que el intérprete probablemente sea más rápido. Si usa uno imperativo, se puede usar un poco menos de memoria y CPU.

Por lo tanto, no importa cómo lo haga, existen ventajas.

Pero, dados dos intérpretes, uno escrito en un idioma imperativo y el otro en uno funcional, y dado además que ambos son correctos, no podría decir de los resultados de un programa qué intérprete se utilizó.

Cuestiones relacionadas