Pregunta

¿Cuáles son las ventajas y limitaciones de los lenguajes de tipo dinámico en comparación con los lenguajes de tipo estático?

Ver también: ¿Qué pasa con el amor por los lenguajes dinámicos? (un hilo mucho más argumentativo...)

¿Fue útil?

Solución

La capacidad del intérprete para deducir tipos y conversiones de tipos hace que el tiempo de desarrollo sea más rápido, pero también puede provocar fallas en el tiempo de ejecución que simplemente no se pueden obtener en un lenguaje de tipo estático donde se detectan en el tiempo de compilación.Pero cuál es mejor (o incluso si eso siempre es cierto) es un tema que se debate acaloradamente en la comunidad estos días (y desde hace mucho tiempo).

Una buena visión del tema proviene de Escritura estática cuando sea posible, escritura dinámica cuando sea necesario:El fin de la guerra fría entre lenguajes de programación por Erik Meijer y Peter Drayton en Microsoft:

Los defensores de la tipificación estática argumentan que las ventajas de la tipificación estática incluyen la detección anterior de errores de programación (por ejemplo,Evitar agregar un entero a un booleano), mejor documentación en forma de firmas de tipo (por ejemplo,Incorporación del número y tipos de argumentos al resolver nombres), más oportunidades para las optimizaciones del compilador (por ejemplo,Reemplazo de llamadas virtuales por llamadas directas Cuando el tipo exacto del receptor se conoce estáticamente), mayor eficiencia en tiempo de ejecución (por ejemplo,No todos los valores deben llevar un tipo dinámico) y una mejor experiencia de desarrollador de tiempo de diseño (por ejemplo,Conociendo el tipo de receptor, el IDE puede presentar un menú desplegable de todos los miembros aplicables).Los fanáticos de la escritura estática intentan hacernos creer que "los programas bien tipo no pueden salir mal".Si bien esto ciertamente suena impresionante, es una declaración bastante vacía.La verificación de tipo estático es una abstracción en tiempo de compilación del comportamiento de tiempo de ejecución de su programa y, por lo tanto, es necesariamente solo parcialmente sólido e incompleto.Esto significa que los programas aún pueden salir mal debido a las propiedades que no son rastreadas por el tipo de verificación, y que hay programas que, si bien no pueden salir mal, no pueden verificarse.El impulso para hacer que la mecanografía estática sea menos parcial y más completa, los sistemas de tipo se vuelven demasiado complicados y exóticos como lo presencian conceptos como "tipos fantasmas" [11] y "tipos tambaleantes" [10].Esto es como tratar de correr un maratón con una pelota y una cadena atada a la pierna y gritando triunfalmente que casi lo lograste a pesar de que te rescataste después de la primera milla.

Los defensores de los idiomas tipados dinámicamente argumentan que la tipificación estática es demasiado rígida, y que la suavidad de los idiomas dinámicos los hace ideales para los sistemas de creación de prototipos con requisitos cambiantes o desconocidos, o que interactúan con otros sistemas que cambian de manera impredecible (datos e integración de aplicaciones).Por supuesto, los idiomas tipados dinámicamente son indispensables para tratar el comportamiento del programa verdaderamente dinámico, como la intercepción de métodos, la carga dinámica, el código móvil, la reflexión del tiempo de ejecución, etc.En la madre de todos los documentos sobre secuencias de comandos [16], John Oulterhout argumenta que los lenguajes de programación de sistemas escrita estáticamente hacen que el código sea menos reutilizable, más detallado, no más seguro y menos expresivo que los lenguajes de secuencia de comandos mecanografiados dinámicamente.Este argumento está literalmente literalmente por muchos proponentes de lenguajes de secuencias de comandos mecanografiados dinámicamente.Argumentamos que esta es una falacia y cae en la misma categoría que argumentando que la esencia de la programación declarativa está eliminando la asignación.O como dice John Hughes [8], es una imposibilidad lógica hacer que un lenguaje sea más poderoso omitiendo las características.Defender el hecho de que retrasar todo lo que verifica el tiempo de ejecución es algo bueno, es jugar tácticas de avestruz con el hecho de que los errores deben captarse lo más temprano posible en el proceso de desarrollo.

Otros consejos

Los sistemas de tipo estático buscan eliminar determinados errores de forma estática, inspeccionando el programa sin ejecutarlo e intentando demostrar su solidez en determinados aspectos.Algunos sistemas de tipos pueden detectar más errores que otros.Por ejemplo, C# puede eliminar excepciones de puntero nulo cuando se usa correctamente, mientras que Java no tiene ese poder.Doce tiene un sistema de tipos que en realidad garantiza que las pruebas terminarán, "resolver" el problema de detención.

Sin embargo, ningún sistema de tipos es perfecto.Para eliminar una clase particular de errores, también deben rechazar ciertos programas perfectamente válidos que violan las reglas.Esta es la razón por la que Twelf realmente no resuelve el problema de la detención, simplemente lo evita descartando una gran cantidad de pruebas perfectamente válidas que terminan de maneras extrañas.Asimismo, el sistema de tipos de Java rechaza el de Clojure. PersistentVector implementación debido al uso de matrices heterogéneas.Funciona en tiempo de ejecución, pero el sistema de tipos no puede verificarlo.

Por esa razón, la mayoría de los sistemas de tipos proporcionan "escapes", formas de anular el verificador estático.Para la mayoría de los lenguajes, estos toman la forma de conversión, aunque algunos (como C# y Haskell) tienen modos completos que están marcados como "inseguros".

Subjetivamente, me gusta la escritura estática.Implementado correctamente (pista: no Java), un sistema de tipo estático puede ser de gran ayuda para eliminar errores antes de que bloqueen el sistema de producción.Los lenguajes escritos dinámicamente tienden a requerir más pruebas unitarias, lo que resulta tedioso en el mejor de los casos.Además, los lenguajes de tipo estático pueden tener ciertas características que son imposibles o inseguras en sistemas de tipo dinámico (conversiones implícitas vienen a la mente).Todo es cuestión de exigencias y gustos subjetivos.No construiría el próximo Eclipse en Ruby, como tampoco intentaría escribir un script de respaldo en ensamblador o parchear un kernel usando Java.

Ah, y la gente que dice eso "X escribir es 10 veces más productivo que y escribir" no son más que humo.La escritura dinámica puede "parecer" más rápida en muchos casos, pero pierde terreno una vez que intentas crear tu aplicación elegante. correr.Del mismo modo, la escritura estática puede parecer la red de seguridad perfecta, pero una mirada a algunas de las definiciones de tipos genéricos más complicadas en Java hace que la mayoría de los desarrolladores busquen anteojeras.Incluso con los sistemas tipográficos y la productividad, no existe una solución milagrosa.

Nota final:No se preocupe por el rendimiento al comparar la escritura estática con la dinámica.Los JIT modernos como V8 y TraceMonkey se están acercando peligrosamente al rendimiento del lenguaje estático.Además, el hecho de que Java en realidad se compila en un lenguaje intermedio inherentemente dinámico debería ser un indicio de que, en la mayoría de los casos, la escritura dinámica no es tan perjudicial para el rendimiento como algunas personas creen que es.

Bueno, ambas cosas son muy, muy, muy muy incomprendidas y además son dos cosas completamente diferentes. que no son mutuamente excluyentes.

Los tipos estáticos son una restricción de la gramática del idioma.Se podría decir estrictamente que los lenguajes escritos estáticamente no están libres de contexto.La simple verdad es que resulta inconveniente expresar un lenguaje sensatamente en gramáticas libres de contexto que no tratan todos sus datos simplemente como vectores de bits.Los sistemas de tipos estáticos son parte de la gramática del idioma, si los hay, simplemente la restringen más de lo que podría hacerlo una gramática libre de contexto, por lo que las comprobaciones gramaticales se realizan en dos pasadas sobre la fuente.Los tipos estáticos corresponden a la noción matemática de teoría de tipos; la teoría de tipos en matemáticas simplemente restringe la legalidad de algunas expresiones.Como, no puedo decir 3 + [4,7] En matemáticas, esto se debe a la teoría de tipos.

Por tanto, los tipos estáticos no son una forma de "prevenir errores" desde una perspectiva teórica, son una limitación de la gramática.De hecho, siempre que +, 3 y los intervalos tengan las definiciones teóricas establecidas habituales, si eliminamos el sistema de tipos 3 + [4,7]tiene un resultado bastante bien definido que es un conjunto.Los 'errores de tipo en tiempo de ejecución' teóricamente no existen, el uso práctico del sistema de tipos es evitar operaciones que a los seres humanos no tendría sentido.Por supuesto, las operaciones siguen siendo sólo el cambio y la manipulación de bits.

El problema de esto es que un sistema de tipos no puede decidir si tales operaciones van a ocurrir o no si se le permitirá ejecutarse.Como en, dividir exactamente el conjunto de todos los programas posibles en aquellos que van a tener un 'error de tipo' y aquellos que no.Sólo puede hacer dos cosas:

1:demostrar que se producirán errores de tipo en un programa
2:demostrar que no van a ocurrir en un programa

Podría parecer que me estoy contradiciendo.Pero lo que hace un verificador de tipo C o Java es rechazar un programa como "agramatical", o como lo llama "error de tipo", si no poder tener éxito en 2.No puede probar que no van a ocurrir, eso no significa que no vayan a ocurrir, simplemente significa que no puede probarlo.Es muy posible que un programa que no tendrá un error de tipo sea rechazado simplemente porque el compilador no puede probarlo.Un ejemplo simple es if(1) a = 3; else a = "string";, seguramente como siempre es cierto, la rama else nunca se ejecutará en el programa y no se producirá ningún error de tipo.Pero no puede probar estos casos de manera general, por lo que se rechaza.Esta es la principal debilidad de muchos lenguajes escritos estáticamente: al protegerte contra ti mismo, necesariamente también estás protegido en los casos en que no lo necesitas.

Pero, contrariamente a la creencia popular, también existen lenguajes tipados estáticamente que funcionan según el principio 1.Simplemente rechazan todos los programas de los que pueden demostrar que van a provocar un error de tipo y aprueban todos los programas de los que no pueden.Por lo tanto, es posible que permitan programas que tengan errores de escritura, un buen ejemplo es Typed Racket, es un híbrido entre escritura dinámica y estática.Y algunos dirían que en este sistema se obtiene lo mejor de ambos mundos.

Otra ventaja de la escritura estática es que los tipos se conocen en el momento de la compilación y, por tanto, el compilador puede utilizarlos.Si lo hacemos en Java "string" + "string" o 3 + 3, ambos + Los tokens en el texto al final representan una operación y un dato completamente diferentes, el compilador sabe cuál elegir entre los tipos solo.

Ahora, voy a hacer una declaración muy controvertida aquí, pero tengan paciencia: La 'tipificación dinámica' no existe.

Suena muy controvertido, pero es cierto, los lenguajes tipados dinámicamente lo son desde una perspectiva teórica. sin escribir.Son simplemente lenguajes tipados estáticamente con un solo tipo.O dicho simplemente, son lenguajes que en la práctica se generan gramaticalmente mediante una gramática libre de contexto.

¿Por qué no tienen tipos?Debido a que cada operación está definida y permitida en cada operante, ¿qué es exactamente un "error de tipo de tiempo de ejecución"?Es de un ejemplo teórico puramente un efecto secundario.si haciendo print("string") que imprime una cadena es una operación, entonces también lo es length(3), el primero tiene el efecto secundario de escribir string a la salida estándar, esta última simplemente error: function 'length' expects array as argument., eso es todo.Desde una perspectiva teórica, no existe un lenguaje tipificado dinámicamente.Ellos son sin escribir

Muy bien, la ventaja obvia del lenguaje 'tipificado dinámicamente' es el poder expresivo, un sistema de tipos no es más que una limitación del poder expresivo.Y, en general, los lenguajes con un sistema de tipos tendrían un resultado definido para todas aquellas operaciones que no están permitidas, si el sistema de tipos simplemente se ignorara, los resultados simplemente no tendrían sentido para los humanos.Muchos lenguajes pierden su integridad Turing después de aplicar un sistema de tipos.

La desventaja obvia es el hecho de que pueden ocurrir operaciones que producirían resultados que no tienen sentido para los humanos.Para protegerse contra esto, los lenguajes tipados dinámicamente típicamente redefinen esas operaciones, en lugar de producir ese resultado sin sentido, lo redefinen para que tenga el efecto secundario de escribir un error y posiblemente detener el programa por completo.Esto no es un "error" en absoluto; de hecho, la especificación del lenguaje generalmente implica esto, es tanto el comportamiento del lenguaje como imprimir una cadena desde una perspectiva teórica.Por lo tanto, los sistemas de tipos obligan al programador a razonar sobre el flujo del código para asegurarse de que esto no suceda.O de hecho, razonar para que hace sucede también puede ser útil en algunos puntos para la depuración, mostrando que no es un "error" en absoluto sino una propiedad bien definida del lenguaje.En efecto, el único resto de "tipificación dinámica" que tienen la mayoría de los lenguajes es protegerse contra una división por cero.Esto es lo que es la escritura dinámica, no hay tipos, no hay más tipos que ese cero es un tipo diferente a todos los demás números.Lo que la gente llama "tipo" es simplemente otra propiedad de un dato, como la longitud de una matriz o el primer carácter de una cadena.Y muchos lenguajes escritos dinámicamente también te permiten escribir cosas como "error: the first character of this string should be a 'z'".

Otra cosa es que los lenguajes tipados dinámicamente tienen el tipo disponible en tiempo de ejecución y normalmente pueden comprobarlo, tratarlo y decidir a partir de él.Por supuesto, en teoría no es diferente a acceder al primer carácter de una matriz y ver qué es.De hecho, puede crear su propio C dinámico, simplemente use solo un tipo como long long int y use los primeros 8 bits para almacenar su 'tipo' y escribir funciones en consecuencia que lo verifiquen y realicen una suma flotante o de enteros.Tiene un lenguaje escrito estáticamente con un tipo o un lenguaje dinámico.

En la práctica, todo esto muestra que los lenguajes escritos estáticamente se usan generalmente en el contexto de escribir software comercial, mientras que los lenguajes escritos dinámicamente tienden a usarse en el contexto de resolver algunos problemas y automatizar algunas tareas.Escribir código en lenguajes escritos estáticamente lleva mucho tiempo y es engorroso porque no puedes hacer cosas que sabes que van a salir bien, pero el sistema de tipos aún te protege contra ti mismo por errores que no cometes.Muchos programadores ni siquiera se dan cuenta de que hacen esto porque está en su sistema, pero cuando codificas en lenguajes estáticos, a menudo evitas el hecho de que el sistema de tipos no te permitirá hacer cosas que no pueden salir mal, porque No puedo probar que no saldrá mal.

Como señalé, "tipificado estáticamente" en general significa caso 2, culpable hasta que se demuestre su inocencia.Pero algunos lenguajes, que no derivan su sistema de tipos de la teoría de tipos en absoluto, utilizan la regla 1:Inocente hasta que se demuestre lo contrario, que podría ser el híbrido ideal.Entonces, tal vez Typed Racket sea para ti.

Además, bueno, para un ejemplo más absurdo y extremo, actualmente estoy implementando un lenguaje donde los 'tipos' son realmente el primer carácter de una matriz, son datos, datos del 'tipo', 'tipo', que en sí mismo es un tipo y un dato, el único dato que se tiene a sí mismo como un tipo.Los tipos no son finitos ni están limitados estáticamente, pero se pueden generar nuevos tipos en función de la información del tiempo de ejecución.

Quizás el mayor "beneficio" de la escritura dinámica es la curva de aprendizaje más superficial.No hay ningún sistema de tipos que aprender ni una sintaxis no trivial para casos extremos como las restricciones de tipos.Esto hace que la escritura dinámica sea accesible para mucha más gente y factible para muchas personas para quienes los sistemas sofisticados de escritura estática están fuera de su alcance.En consecuencia, la tipificación dinámica se ha popularizado en los contextos educativos (p. ej.Scheme/Python en el MIT) y lenguajes de dominio específico para no programadores (p. ej. Matemáticas).Los lenguajes dinámicos también se han popularizado en nichos donde tienen poca o ninguna competencia (por ejemplo,JavaScript).

Los lenguajes de tipado dinámico más concisos (p. ej.Perl, APL, J, K, Matemáticas) son específicos de un dominio y pueden ser significativamente más concisos que los lenguajes tipificados estáticamente de propósito general más concisos (p. ej. OCaml) en los nichos para los que fueron diseñados.

Las principales desventajas de la escritura dinámica son:

  • Errores de tipo en tiempo de ejecución.

  • Puede ser muy difícil o incluso prácticamente imposible alcanzar el mismo nivel de corrección y requiere muchas más pruebas.

  • No hay documentación verificada por el compilador.

  • Rendimiento deficiente (normalmente en tiempo de ejecución, pero a veces en tiempo de compilación, p. ej.Stalin Scheme) y rendimiento impredecible debido a la dependencia de optimizaciones sofisticadas.

Personalmente, crecí con lenguajes dinámicos, pero no los tocaría ni con un palo de 40' como profesional a menos que no hubiera otras opciones viables.

De Artima's Mecanografía:Fuerte vs.Débil, Estático vs.Dinámica artículo:

La escritura fuerte evita operaciones de mezcla entre tipos no coincidentes.Para mezclar tipos, debe utilizar una conversión explícita

La escritura débil significa que puedes mezclar tipos sin una conversión explícita.

En el artículo de Pascal Costanza, Dinámico vs.Escritura estática: un análisis basado en patrones (PDF), afirma que, en algunos casos, la escritura estática es más propensa a errores que la escritura dinámica.Algunos lenguajes de escritura estática te obligan a emular manualmente la escritura dinámica para poder hacer "lo correcto".Se discute en Lambda lo último.

Depende del contexto.Hay muchos beneficios que son apropiados tanto para el sistema de tipo dinámico como para el de tipo fuerte.Soy de la opinión de que el flujo del lenguaje de tipos dinámicos es más rápido.Los lenguajes dinámicos no están limitados por atributos de clase ni por el pensamiento del compilador sobre lo que sucede en el código.Tienes algo de libertad.Además, el lenguaje dinámico suele ser más expresivo y genera menos código, lo cual es bueno.A pesar de esto, es más propenso a errores, lo que también es cuestionable y depende más de la cobertura de pruebas unitarias.Es un prototipo fácil con un lenguaje dinámico, pero el mantenimiento puede convertirse en una pesadilla.

La principal ventaja sobre el sistema de tipo estático es la compatibilidad con IDE y, seguramente, el analizador de código estático.Tienes más confianza en el código después de cada cambio de código.El mantenimiento es pan comido con este tipo de herramientas.

Hay muchas cosas diferentes acerca de los lenguajes estáticos y dinámicos.Para mí, la principal diferencia es que en los lenguajes dinámicos las variables no tienen tipos fijos;en cambio, los tipos están vinculados a valores.Debido a esto, el código exacto que se ejecuta no se determina hasta el tiempo de ejecución.

En implementaciones tempranas o ingenuas, esto supone un enorme lastre para el rendimiento, pero los JIT modernos se acercan tentadoramente a lo mejor que se puede conseguir optimizando los compiladores estáticos.(en algunos casos marginales, incluso mejor que eso).

Se trata de la herramienta adecuada para el trabajo.Ninguno de los dos es mejor el 100% de las veces.Ambos sistemas fueron creados por el hombre y tienen fallas.Lo siento, pero apestamos y hacemos cosas perfectas.

Me gusta la escritura dinámica porque se quita de mi camino, pero sí, pueden aparecer errores de tiempo de ejecución que no había planeado.Mientras que la escritura estática puede corregir los errores antes mencionados, pero vuelve loco a un programador novato (en lenguajes mecanografiados) al intentar convertir entre un carácter constante y una cadena.

Escritura estática:Los lenguajes como Java y Scala son de tipo estático.

Las variables deben definirse e inicializarse antes de usarse en un código.

por ej.intx;x = 10;

System.out.println(x);

Escritura dinámica:Perl es un lenguaje de tipo dinámico.

No es necesario inicializar las variables antes de utilizarlas en el código.

y=10;use esta variable en la última parte del código

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