Pregunta

Amigos, preguntas simples:Hago mucha programación (profesional y personalmente) en lenguajes compilados como C++/Java y en lenguajes interpretados como Python/Javascript.Personalmente encuentro que mi código casi siempre es más robusto cuando programo en lenguajes escritos estáticamente.Sin embargo, casi todos los lenguajes interpretados que encuentro utilizan escritura dinámica (PHP, Perl, Python, etc.).Sé por qué los lenguajes compilados usan escritura estática (la mayor parte del tiempo), pero no puedo entender la aversión a la escritura estática en el diseño de lenguaje interpretado.

¿A qué se debe esta abrupta desconexión?¿Es parte de la naturaleza de las lenguas interpretadas?¿POO?

¿Fue útil?

Solución

Es una pregunta interesante. Por cierto, yo soy el autor / mantenedor de APS (compilador para PHP), y estoy haciendo mi doctorado en compiladores para lenguajes dinámicos , por lo que espero que pueda ofrecer algunas ideas.

Creo que hay una suposición errónea de aquí. Los autores de PHP, Perl, Python, Ruby, Lua, etc no diseñaron "lenguajes interpretados", diseñaron los lenguajes dinámicos, y los implementan utilizando intérpretes. Hicieron esto porque los intérpretes son mucho más fáciles de escribir que los compiladores.

primera implementación de Java fue interpretado, y es un lenguaje de tipos estáticos. ¿Existen intérpretes para lenguajes estáticos: Haskell y OCaml ambos tienen intérpretes, y hay que solía ser un intérprete popular para C, pero eso fue hace mucho tiempo. Son muy populares porque permiten una REPL , lo que puede hacer que el desarrollo sea más fácil.

Dicho esto, hay una aversión a los tipos estáticos en la comunidad lenguaje dinámico, como era de esperar. Ellos creen que los sistemas de tipo estático proporcionados por C, C ++ y Java son verbosa, y no vale la pena el esfuerzo. Creo que estoy de acuerdo con esto, en cierta medida. Programación en Python es mucho más divertido que C ++.

Para hacer frente a los puntos de los demás:

  • dlamblin dice : "Nunca me sentí fuertemente que había algo especial acerca de la compilación vs interpretación dinámica que sugiere sobre tipos estáticos". Bueno, estás muy equivocado. Compilación de lenguajes dinámicos es muy difícil. No es sobre todo la declaración eval tener en cuenta, que se utiliza ampliamente en Javascript y Ruby. PHC compila PHP por delante de los tiempos, pero todavía necesita un intérprete de tiempo de ejecución a evals mango. eval también no puede ser analizada de forma estática en un compilador de optimización, aunque hay un fría técnica si no es necesario solidez.

  • Para la respuesta de damblin a Andrew Hare : por supuesto podría realizar el análisis estático de un intérprete, y encontrar errores antes en tiempo de ejecución, que es exactamente lo que hace ghci de Haskell. Espero que el estilo del intérprete utilizado en los lenguajes funcionales requiere esto. dlamblin Por supuesto, es correcto decir que el análisis no es parte de la interpretación.

  • Andrew Hare respuesta se basa en la suposición errónea de interrogadores, y de manera similar tiene las cosas al revés. Sin embargo, se plantea una pregunta interesante: "lo difícil es el análisis estático de los lenguajes dinámicos?". Muy muy difícil. Básicamente, usted obtendrá un doctorado para describir cómo funciona, que es exactamente lo que estoy haciendo. Véase también el punto anterior.

  • La respuesta más correcta hasta el momento es el de Ivo Wetzel . Sin embargo, los puntos que se describen pueden ser manejados en tiempo de ejecución en un compilador, y existen muchos compiladores de Lisp y Scheme que tienen este tipo de enlace dinámico. Pero, sí, es complicado.

Otros consejos

Los lenguajes interpretados utilizan tipado dinámico porque no hay paso de compilación en el que hacer el análisis estático. lenguajes compilados hacen análisis estático en tiempo de compilación lo que significa que cualquier error de tipo sean notificados al desarrollador a medida que trabajan.

Es más fácil de entender si tenemos en cuenta que un lenguaje de tipos estáticos tiene un compilador que Aplica el tipo de reglas fuera del contexto de ejecución. Los lenguajes interpretados son nunca analizó de manera estática tipo reglas deben ser aplicadas por el intérprete en el contexto de la ejecución.

Creo que es debido a la naturaleza de los lenguajes interpretados, quieren ser dinámicos, por lo que puede cambiar las cosas en tiempo de ejecución. Debido a esto un compilador no sabe exactamente cuál es el estado del programa después de la siguiente línea de código se ha excecuted.

Imaginemos el siguiente escenario (en Python):

import random
foo = 1

def doSomeStuffWithFoo():
    global foo
    foo = random.randint(0, 1)

def asign():
    global foo
    if foo == 1:
        return 20
    else:
        return "Test"


def toBeStaticallyAnalyzed():
    myValue = asign()

    # A "Compiler" may throw an error here because foo == 0, but at runtime foo maybe 1, so the compiler would be wrong with its assumption
    myValue += 20


doSomeStuffWithFoo() # Foo could be 1 or 0 now... or 4 ;)
toBeStaticallyAnalyzed()

A medida que se espera que puedan ver, un compilador no tendría ningún sentido en esta situación. Acutally que le podría advertir sobre la posibilidad de que "myValue" tal vez algo más que un número. Pero entonces, en JavaScript que fallaría porque si "myValue" es una cadena, 20 serían implictily convierte en una cadena también, por lo tanto, se produciría ningún error. Así que se podría obtener miles de avisos inútiles por todo el lugar, y no creo que esa es la intención de un compilador.

La flexibilidad siempre viene con un precio, es necesario tomar una mirada más profunda en su programa, o programa con más cuidado, en otras palabras, usted es el compilador en situaciones como la anterior.

Así que su solución como el compilador? - Fijar con una "probar: excepto":)

Compiladores + tipos estáticos = código de máquina eficiente
Compiladores + tipos dinámicos = código de máquina ineficiente

Considere el siguiente pseudocódigo:

function foo(a, b) {
    return a+b
}

Un lenguaje estático podrá saber (por declaración o inferencia) que a y b son números enteros y se compilará hasta

%reg = addi a,b

o algo similar, de todos modos.

Un compilador para un lenguaje dinámico tendría que emitir código para
1.Comprueba los tipos de a y b
2.manejar cada caso o combinación de casos

%reg1 = typeof a
beq %reg1, int, a_int_case
beq %reg1, float, a_float_case
beq %reg1, string, a_string_case

label a_int_case
%reg1 = typeof b
beq %reg1, int, a_int_b_int_case
beq %reg1, float, a_int_b_float_case
beq %reg1, string, a_int_b_string_case

label a_int_b_int_case
%out = addi a,b
goto done

label a_int_b_float_case
%tmp = mkfloat a
%out = addf %tmp,b
goto done

... Etc. I can't finish

Si bien podría generar un código de máquina más inteligente que ese, no podría evitar generar una gran cantidad de código. Eso hace que la compilación no sea una gran ventaja para un lenguaje dinámico.

Dado que los intérpretes son mucho más fáciles de escribir y la compilación no sirve de mucho, ¿por qué no escribir un intérprete?

(Los compiladores justo a tiempo en realidad tienen información de tipo y pueden compilar hasta una sola declaración.En realidad, tienen más información que los sistemas de tipo estático y, en teoría, pueden funcionar incluso mejor.Todo el ensamblador está simulado;Cualquier parecido con código real que podría ejecutarse en una máquina real es pura coincidencia).

Tal vez sea porque uno de mis principales lenguajes interpretados es Perl y uno de mis lenguajes compilados es Objective-C, pero nunca me sentí fuertemente que había algo especial acerca de la compilación vs interpretación dinámica sugerido sobre tipos estáticos.

Creo que es evidente que las dos partes esperan en el otro y pensando, "Hay algunas ventajas a eso." Es más fácil en varias aplicaciones para obtener algún tipo dinámico flexibilidad, mientras que puede ser más fácil de mantener algo que está estático de tipos y ejecutada.

Andrew Hare explicación sin embargo. Mientras que un lenguaje puramente interpretado tendría que añadir en una etapa de procesamiento previo, y por lo tanto no puede ser puramente interpretada con el fin de advertir al programador antes de la ejecución de los errores de escritura estáticas, no impedirá lanzar un error de tipo en tiempo de ejecución, ya que se produce. Por lo que carece de compilación no significa que se puede producir ninguna comprobación de tipo estático. Pero dado que la obtención de un error de tipo en tiempo de ejecución no es tan útil como conseguir uno a la compilación, o durante una comprobación previa, puedo ver cómo la "ventaja" de tipos estáticos en esa situación puede parecer más una molestia, y por lo tanto son arrojados a favor de las ventajas tipado dinámico traer.

Si sabía desde el principio que prefiere mantener su tipo estático, porque personalmente a escribir código mejor y más fácil de mantener, como resultado, y que estaba diseñando su lenguaje interpretado, nada debe impedirle el diseño de la lengua como uno estático de tipos .

Para citar el lenguajes interpretados wiki artículo "En teoría, cualquier lenguaje puede ser compilado o interpretado , por lo que esta designación se aplica únicamente a causa de la práctica común de aplicación y no una propiedad subyacente de un idioma. "
Hay un decente wiki artículo sólo en el escribir.

tipos dinámicos lenguajes interpretados le dan más libertad en la forma de programar. Permite la programación meta a ser factible. Permite variables que se crean en tiempo de ejecución. Permite hashes y arrays anónimos anónimos para ser creados en un momento dado durante el tiempo de ejecución sin tener que declarar previamente nada de antemano. Se permite que la información indeterminada que va inputed en un hash sin tener que declarar todas las claves de antemano. Usted puede tener subrutinas creadas a partir de la entrada al azar indeterminado. Se puede alimentar a un código de programa también que se puede ejecutar de forma dinámica. Los lenguajes interpretados liberar las cadenas de la cual los límites de la programación en general. Usted está limitado a lo que se escribe en el archivo de origen con los lenguajes de tipos estáticos. Puede hacer más con menos en un lenguaje de tipos dinámicos.

La mayoría de los robots se hacen hoy en día trato con lenguajes interpretados más debido a las necesidades de información que se determinará en tiempo de ejecución y necesitan ser hechas para almacenar esta información en tiempo de ejecución de nuevas variables. se interpreta la información en torno a la máquina de aprendizaje. Nosotros mismos, como seres humanos son los intérpretes por lo que los robots están siendo diseñados de esa manera. El futuro realmente se interpreta. Por supuesto que necesitamos estático de tipos idiomas a intérpretes compilación por lo lenguas tipos estáticos nunca desaparecerán a menos que los intérpretes se construyen en código ensamblador en el futuro. La mayoría de los intérpretes se basan en lenguajes con tipos estáticos en estos días.

Los lenguajes interpretados sobresalir en un entorno dinámico. Si se puede interpretar nuevo código / datos en tiempo de ejecución a continuación, por qué no. Si su realmente bueno en programación dinámica a continuación, puede crear un código que puede crear variables y valores hash sin tener que escribir todo lo que fuera. Puede reducir la cantidad de líneas drásticamente si su trabajo con grandes cantidades de datos. Puede utilizar un descargador de datos para imprimir toda la información de los lenguajes interpretados, porque por lo general no perder de vista el tipo de variables en tiempo de ejecución que permite que esto sea posible. No se puede hacer esto en barebones C ++. El único momento en C ++ y C sabe lo que está pasando es en tiempo de compilación. Después de que su por su cuenta a menos que implemente algo por sí mismo.

¿Quién quiere estar atado tanto al archivo de origen en estos días sobre todo cuando su trabajo en entornos dinámicos. Todo lo que estás haciendo está limitando su potencial. Una vez que su cuello en forma dinámica interpretarse código y volver a cualquier lenguaje de tipos estáticos le resultará más difícil de embrutecer su código porque su pensando todavía en un estado mental sin límites. Sus mente necesita para volver de nuevo a estar limitado de nuevo a lo que está escrito en el archivo de origen.

En el modo de programación de estilos: código estático de tipos produce resultados estáticos. Código de tipos dinámicos produce dinámica o estática resultados.

Si vas a ser la programación de algo que nunca cambia el comportamiento distinto de lo que se conocía entonces lenguas tipos estáticos son ideales para eso. Si su trato con comportamiento dinámico continuación idiomas tipos dinámicos son más adecuados para esos casos. Todo depende de la situación en su mayoría.

Cada idioma tiene sus altibajos. Sólo tienes que escoger y elegir sabiamente.

Creo tipos estáticos hace que sea más fácil para los compiladores y esa es la principal (si no la única) razón por la que está presente en lenguajes compilados.

Para los lenguajes interpretados es más fácil suponer que las variables no tienen tipo (sólo valores tienen), ya que son considerados no como un placer para los datos que deben caber dentro, sino más bien la etiqueta para los datos que flota en algún lugar en el montón .

Si programador falta es que siempre se puede afirmar que la variable contiene un valor de tipo determinado (por ejemplo, en la asignación). No hay ninguna razón para construirlo en la lengua. Por supuesto que no es el mismo tipo de control que tiene para lenguajes compilados.

Probablemente podría tener un lenguaje en el que usted tiene que declarar explícitamente el tipo de cada variable, pero si no lo hace es mucho más fácil de hacer las cosas interesantes que con tipos estáticos requerirían del programador muy cuidadosamente hechos a mano los tipos genéricos complejas.

Por otro lado. ¿Usted sabe cualquier lenguaje de tipos dinámicos compilado (estáticamente, no JIT)?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top