¿La sintaxis de los lenguajes de programación depende de su implementación?

12

Aunque, mi pregunta puede ser totalmente irrelevante, pero he detectado un patrón entre la mayoría de los lenguajes de programación y sus implementaciones oficiales.

Los lenguajes

interpretados (¿interpretados en bytes?) como Python, Lua, etc., generalmente tienen una sintaxis extremadamente indulgente y fácil y generalmente no tienen tipo o no requieren que el desarrollador escriba explícitamente tipos de variables en código fuente;

Los lenguajes

compilados como C, C ++, Pascal, etc. generalmente tienen una sintaxis estricta, generalmente tienen tipos y en su mayoría requieren más código / tiempo de desarrollo

Los lenguajes cuyas implementaciones oficiales son compiladas con JIT como Java / C # generalmente son un compromiso único entre los dos anteriores con algunas de las mejores características de ambos.

Algunos de los lenguajes de programación compilados más modernos como D y Vala (y la implementación GNU GJC de Java) son quizás una excepción a esta regla y se parecen a la sintaxis y las características de los lenguajes compilados por JIT como Java y C #.

Mi primera pregunta es, ¿es esto realmente relevante? ¿O es solo una coincidencia que la mayoría de los lenguajes interpretados tienen una sintaxis fácil, los compilados por JIT tienen una sintaxis y características moderadas, etc.?

En segundo lugar, si esto no es una coincidencia, entonces ¿por qué es así? Como, por ejemplo, ¿algunas funciones solo pueden implementarse en un lenguaje de programación si, por ejemplo, está compilando JIT?

    
pregunta ApprenticeHacker 21.12.2011 - 07:24

5 respuestas

17

No hay conexión alguna entre la semántica y la sintaxis. Los lenguajes homoicónicos compilados como Scheme vienen con una sintaxis bastante minimalista. Los meta-lenguajes compilados de bajo nivel como Forth son incluso más simples que eso. Algunos lenguajes compilados muy estrictamente escritos se basan en una sintaxis trivial (think ML, Haskell). OTOH, la sintaxis de Python es muy pesada, en términos de una serie de reglas de sintaxis.

Y sí, la escritura no tiene nada que ver con la sintaxis, está en el lado semántico de un lenguaje, a menos que sea algo tan pervertido como C ++, donde ni siquiera se puede analizar sin tener toda la información de escritura disponible.

Una tendencia general es que los idiomas que evolucionaron durante demasiado tiempo y que no contenían ninguna protección de diseño contra las desviaciones de sintaxis, tarde o temprano se convertirían en abominaciones sintácticas.

    
respondido por el SK-logic 21.12.2011 - 09:25
6

Sobre todo esto es una coincidencia.

Los lenguajes de programación han evolucionado con el tiempo y la tecnología de los compiladores e intérpretes ha mejorado. La eficiencia del procesamiento subyacente (es decir, el tiempo de compilación, la sobrecarga de interpretación, el tiempo de ejecución, etc.) también es menos importante ya que las plataformas informáticas principales han aumentado su poder.

La sintaxis del lenguaje tiene un impacto, por ejemplo, Pascal fue diseñado con mucho cuidado para que pudiera usar un compilador de un solo paso, es decir, una pasada sobre la fuente y tiene un código de máquina excelente. Ada, por otra parte, no prestó atención a esto, y los compiladores de Ada son muy difíciles de escribir; la mayoría requiere más de un pase. (Un muy buen compilador de Ada que utilicé hace muchos años era un compilador de 8 pases. Como pueden imaginar, era muy lento).

Si nos fijamos en lenguajes antiguos como Fortran (compilado) y BÁSICO (interpretados o compilados), tienen / tienen reglas de sintaxis y semánticas muy estrictas. [En el caso de BASIC, que no es Bills anterior a BASIC, debe volver antes al original.]

Por otro lado, al mirar otras cosas más antiguas como APL (un montón de diversión) esto tuvo una tipificación dinámica, de algún tipo. También se interpretó en general, pero también se pudo compilar.

La sintaxis de Lenient es difícil: si eso significa que tienes cosas que son opcionales o que se pueden inferir, significa que el idioma tiene la suficiente riqueza como para poder eliminarlo. ¡De nuevo, BASIC lo tuvo hace muchos años cuando la declaración "LET" se convirtió en opcional!

Muchas de las ideas que ve ahora (por ejemplo, tipografías dinámicas o sin tipo de letra) son en realidad muy antiguas: aparecieron por primera vez en los años 70 o principios de los 80. La forma en que se usan y los idiomas en que se usan estas ideas ha cambiado y crecido. Pero fundamentalmente, gran parte de lo nuevo es en realidad cosas viejas vestidas con ropa nueva.

Aquí hay algunos ejemplos de la parte superior de mi cabeza:

  • APL: escritura dinámica. Generalmente interpretada. Vino de los años sesenta / setenta.
  • BÁSICO: escritura fuerte o dinámica. Interpretado o compilado. 1970 y muchos más allá.
  • Fortran: mecanografía fuerte. Compilado 1960 o antes.
  • Algol68: mecanografía fuerte. Compilado 1960's.
  • PL / 1: escritura fuerte. Compilado 1960's.
  • Pascal: mecanografía fuerte. Compilado 1970's. (¡Pero en la década de 1980 había compiladores P-System muy similares a los compiladores JIT!)
  • Algunas implementaciones de Fortran y otras de DEC en los primeros días se compilaron parcialmente y se interpretaron parcialmente.
  • Smalltalk: escritura dinámica. Compilado a bytecode que se interpreta. 1980's.
  • Prólogo: más extraña. Funcional. Compilado (Turbo Prolog, alguien?). 1980's.
  • C: tipificación fuerte (ja ja). Compilado 1960's..today.
  • Ada: mecanografía súper fuerte. Compilado 1980's.
  • Perl: escritura dinámica. (Sintaxis fuerte). Interpretado. 1990's (?).

Podría seguir.

  • Nitpickers corner: muchos idiomas interpretados se tokenizan o "compilan en bytes" en el momento en que se cargan / leen la fuente. Esto hace que la operación posterior del intérprete sea mucho más simple. A veces puede guardar la versión compilada en bytes del código. A veces no puedes. Todavía se interpreta.

Actualización: porque no estaba lo suficientemente claro.

La escritura puede variar ampliamente.

La escritura estática fija en tiempo de compilación es común (por ejemplo, C, Ada, C ++, Fortan, etc., etc.). Aquí es donde declaras una COSA de un TIPO y es así para siempre.

También es posible tener una escritura dinámica, donde la cosa recoge el tipo que se le asigna. Por ejemplo, PHP y algunas versiones BÁSICAS, y APL, donde asignaría un entero a una variable y desde ese momento era un tipo entero. Si luego le asignó una cadena, entonces era un tipo de cadena. Y así sucesivamente.

Y luego está la escritura suelta, por ejemplo, PHP, donde puedes hacer cosas realmente extrañas, como asignar un entero numérico (citado, por lo que es una cadena) a una variable y luego agregarle un número. (por ejemplo, '5' + 5 daría como resultado 10). Esta es la tierra de lo extraño, pero a veces también es muy útil.

SIN EMBARGO, estas son características diseñadas en un idioma. La implementación solo hace que eso suceda.

    
respondido por el quickly_now 21.12.2011 - 08:08
2

Creo que es al revés: la implementación depende de la sintaxis. Por ejemplo, si su sintaxis permite la reflexión, entonces la implementación debe proporcionar un tiempo de ejecución que admita eso.

    
respondido por el StackedCrooked 21.12.2011 - 09:43
2

Generalmente estoy de acuerdo con quick_now en que su observación es principalmente un resultado de la historia. Dicho esto, el razonamiento subyacente se reduce a algo como esto:

The more modern a language is, the more comfortable it should be to use.

(No es una cita realmente, solo mi propia formulación). Cuando escribo comfortable aquí, me refiero a lo que llamaste best features of both . Más precisamente, no quiero hablar a favor o en contra de la escritura estática / dinámica o la sintaxis estricta / indulgente. En su lugar, es importante ver cómo los desarrolladores se centran y aumentan su nivel de comodidad cuando trabajan con el idioma.

Aquí hay algunas razones, que no se han mencionado en las respuestas anteriores, que pueden proporcionarle algunas ideas de por qué observa estas cosas (y todas están basadas en la historia del desarrollo del lenguaje de programación):

  • Tenemos cientos de lenguajes de programación en estos días. Cuando surge una nueva, ¿cómo puede encontrar una amplia audiencia? Esta es la razón principal por la que los nuevos idiomas siempre intentan aumentar el nivel de comodidad de los desarrolladores. Si el idioma puede hacer lo mismo que el anterior, puede hacerlo mucho más fácil / más simple / más elegante / etc. es posible que desee considerar realmente cambiar.

  • La curva de aprendizaje va de la mano con eso. En el pasado, teníamos pocos idiomas y el tiempo de inversión para aprender uno valía la pena. Incluso si eso significaba invertir mucho tiempo. La comodidad aumenta nuevamente, si se le ocurre un lenguaje que los desarrolladores puedan aprender muy rápidamente. La complejidad de cualquier tipo (p. Ej., Sintaxis complicada involucrada) es perjudicial para esto y, por lo tanto, se reduce cada vez más en idiomas más nuevos.

  • Los avances tecnológicos (una razón histórica directa aquí) son responsables de que los compiladores del compilador ahora puedan concentrarse más en la comodidad del desarrollador. En los primeros días, estábamos felices de poder construir un compilador en absoluto. Sin embargo, eso a menudo implicaba fuertes restricciones. A medida que aumentaron los conocimientos tecnológicos, pudimos levantar estas restricciones nuevamente.

Entonces, en general, los lenguajes de programación y los compiladores han visto un desarrollo similar al de las aplicaciones típicas de usuarios finales:

  1. Etapa inicial: es genial tenerla, pero la tecnología de vanguardia apenas hace que funcione a costa de la comodidad / usabilidad / lo que no.
  2. Mejora tecnológica: podemos construir estas cosas de manera más robusta, más rápida y más fácil.
  3. El enfoque se dirige al usuario: al igual que el movimiento Web 2.0 que se centra en la experiencia del usuario, los nuevos lenguajes de programación se centran en la perspectiva del desarrollador.
respondido por el Frank 21.12.2011 - 09:45
0

Un lenguaje de programación dado puede o no exponer o restringir suficiente información semántica para que un compilador deduzca cómo reducirlo a código ejecutable sin decisiones de tiempo de ejecución agregadas ("¿de qué tipo es esta variable?", etc.) Algunos lenguajes son explícitamente diseñado para hacer que esta restricción sea obligatoria o fácil de determinar.

A medida que los compiladores se vuelven más inteligentes, pueden adivinar o perfilar suficiente información para generar código ejecutable para las rutas más probables, incluso para idiomas que no fueron diseñados explícitamente para exponer o limitar esas decisiones.

Sin embargo, los idiomas donde el código (evalString ()) se puede crear o ingresar en tiempo de ejecución (y otras cosas que el compilador no puede deducir o adivinar) pueden requerir que un intérprete o compilador JIT esté disponible en tiempo de ejecución, incluso con intentos para precompilarlos.

En el pasado, un lenguaje de programación y su implementación podrían haber evolucionado para adaptarse a alguna restricción de hardware, como si el intérprete podría encajar en 4k o 16k, o si el compilador podría terminar en menos de un minuto de tiempo de CPU . A medida que las máquinas se vuelven más rápidas, es posible (re) compilar algunos programas interpretados anteriormente tan rápido como el programador puede presionar la tecla de retorno, o interpretar el código fuente del programa antes compilado más rápido que el hardware un poco más antiguo podría ejecutar ejecutables compilados optimizados.

    
respondido por el hotpaw2 21.12.2011 - 13:02

Lea otras preguntas en las etiquetas