Idiomas compilados versus lenguajes interpretados

Resuelto chimeracoder asked hace 14 años • 13 respuestas

Estoy tratando de comprender mejor la diferencia. He encontrado muchas explicaciones en línea, pero tienden a diferencias abstractas más que a implicaciones prácticas.

La mayor parte de mis experiencias de programación han sido con CPython (dinámico, interpretado) y Java (estático, compilado). Sin embargo, entiendo que existen otros tipos de lenguajes interpretados y compilados. Aparte del hecho de que los archivos ejecutables se pueden distribuir desde programas escritos en lenguajes compilados, ¿hay ventajas/desventajas para cada tipo? A menudo escucho a personas argumentar que los lenguajes interpretados se pueden usar de forma interactiva, pero creo que los lenguajes compilados también pueden tener implementaciones interactivas, ¿correcto?

chimeracoder avatar Jul 16 '10 20:07 chimeracoder
Aceptado

Un lenguaje compilado es aquel en el que el programa, una vez compilado, se expresa en las instrucciones de la máquina de destino. Por ejemplo, una operación de adición "+" en su código fuente podría traducirse directamente a la instrucción "ADD" en código de máquina.

Un lenguaje interpretado es aquel en el que las instrucciones no son ejecutadas directamente por la máquina de destino, sino que algún otro programa las lee y ejecuta (que normalmente está escrito en el lenguaje de la máquina nativa). Por ejemplo, la misma operación "+" sería reconocida por el intérprete en tiempo de ejecución, que luego llamaría a su propia función "add(a,b)" con los argumentos apropiados, que luego ejecutaría la instrucción "ADD" en código de máquina. .

Puede hacer cualquier cosa que pueda hacer en un lenguaje interpretado en un lenguaje compilado y viceversa; ambos son Turing completos. Sin embargo, ambos tienen ventajas y desventajas para la implementación y el uso.

Voy a generalizar completamente (¡los puristas me perdonan!) pero, a grandes rasgos, estas son las ventajas de los lenguajes compilados:

  • Rendimiento más rápido utilizando directamente el código nativo de la máquina de destino
  • Oportunidad de aplicar optimizaciones bastante poderosas durante la etapa de compilación.

Y aquí están las ventajas de los lenguajes interpretados:

  • Más fácil de implementar (¡escribir buenos compiladores es muy difícil!)
  • No es necesario ejecutar una etapa de compilación: puede ejecutar el código directamente "sobre la marcha"
  • Puede ser más conveniente para lenguajes dinámicos.

Tenga en cuenta que las técnicas modernas, como la compilación de códigos de bytes, añaden cierta complejidad adicional; lo que sucede aquí es que el compilador apunta a una "máquina virtual" que no es la misma que el hardware subyacente. Estas instrucciones de la máquina virtual se pueden compilar nuevamente en una etapa posterior para obtener código nativo (por ejemplo, como lo hace el compilador Java JVM JIT).

mikera avatar Jul 16 '2010 14:07 mikera

Un lenguaje en sí no se compila ni se interpreta, sólo lo es una implementación específica de un lenguaje. Java es un ejemplo perfecto. Hay una plataforma basada en código de bytes (JVM), un compilador nativo (gcj) y un intérprete para un superconjunto de Java (bsh). Entonces, ¿qué es Java ahora? ¿Compilado con código de bytes, compilado de forma nativa o interpretado?

Otros lenguajes que se compilan e interpretan son Scala, Haskell u Ocaml. Cada uno de estos lenguajes tiene un intérprete interactivo, así como un compilador en código de bytes o código de máquina nativo.

Por lo tanto, en general, categorizar los idiomas como "compilados" e "interpretados" no tiene mucho sentido.

 avatar Jul 16 '2010 14:07

Los casos extremos y simples:

  • Un compilador producirá un ejecutable binario en el formato ejecutable nativo de la máquina de destino. Este archivo binario contiene todos los recursos necesarios excepto las bibliotecas del sistema; está listo para ejecutarse sin más preparación ni procesamiento y se ejecuta como un rayo porque el código es el código nativo para la CPU en la máquina de destino.

  • Un intérprete presentará al usuario un mensaje en un bucle donde puede ingresar declaraciones o código, y al presionar RUNo su equivalente, el intérprete examinará, escaneará, analizará y ejecutará interpretativamente cada línea hasta que el programa se ejecute hasta un punto de parada o un error. . Debido a que cada línea se trata por sí sola y el intérprete no "aprende" nada de haber visto la línea antes, el esfuerzo de convertir el lenguaje legible por humanos en instrucciones de máquina se realiza cada vez para cada línea, por lo que es muy lento. Lo bueno es que el usuario puede inspeccionar e interactuar con su programa de muchas maneras: cambiando variables, cambiando código, ejecutándolo en modos de rastreo o depuración... lo que sea.

Una vez aclarados estos problemas, permítanme explicarles que la vida ya no es tan sencilla. Por ejemplo,

  • Muchos intérpretes precompilarán el código que se les proporciona para que el paso de traducción no tenga que repetirse una y otra vez.
  • Algunos compiladores no compilan según instrucciones de máquina específicas de la CPU, sino según código de bytes, una especie de código de máquina artificial para una máquina ficticia. Esto hace que el programa compilado sea un poco más portátil, pero requiere un intérprete de código de bytes en cada sistema de destino.
  • Los intérpretes de código de bytes (estoy viendo Java aquí) recientemente tienden a volver a compilar el código de bytes que obtienen para la CPU de la sección de destino justo antes de la ejecución (llamado JIT). Para ahorrar tiempo, esto a menudo solo se hace para el código que se ejecuta con frecuencia (puntos de acceso).
  • Algunos sistemas que parecen y actúan como intérpretes (Clojure, por ejemplo) compilan cualquier código que obtienen, inmediatamente, pero permiten el acceso interactivo al entorno del programa. Esa es básicamente la conveniencia de los intérpretes con la velocidad de la compilación binaria.
  • Algunos compiladores realmente no compilan, simplemente digieren previamente y comprimen el código. Hace un tiempo escuché que así es como funciona Perl. Entonces, a veces el compilador solo está haciendo una parte del trabajo y la mayor parte sigue siendo interpretación.

Al final, hoy en día, interpretar versus compilar es una compensación, ya que el tiempo dedicado (una vez) a compilar a menudo se ve recompensado por un mejor rendimiento en tiempo de ejecución, pero un entorno interpretativo que brinda más oportunidades de interacción. Compilar versus interpretar es principalmente una cuestión de cómo se divide el trabajo de "comprender" el programa entre diferentes procesos, y la línea es un poco borrosa hoy en día ya que los lenguajes y productos intentan ofrecer lo mejor de ambos mundos.

Carl Smotricz avatar Jul 16 '2010 13:07 Carl Smotricz