Lenguajes de tipo dinámico versus lenguajes de tipo estático

205

¿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 ...)

cvs
fuente
10
Esta pregunta es demasiado subjetiva.
Jason Dagit
77
No lo llamaría subjetivo, sino cebo de llamas. Pero hay algunos hechos objetivos al respecto.
Vinko Vrsalovic
2
De acuerdo: demasiado subjetivo. Es interesante comparar y contrastar los dos enfoques, pero se tambalea peligrosamente al borde del apocalipsis del foro.
Daniel Spiewak
17
Los lenguajes dinámicos son excelentes para el desarrollo rápido de aplicaciones de demostración / descartables porque si crea un error tipográfico que le importa, la página web aún se carga, es posible que tenga un par de elementos de datos incorrectos aquí o allá. No puedo imaginar ninguna otra situación en la que la capacidad de escribir mal sus variables sin obtener un error del compilador se vea como una "ventaja".
Alex R
44
Tal error típicamente detendría a JavaScript, lo cual considero algo muy bueno. Por lo menos arrojaría errores que también encuentro valiosos. Por alguna razón, siempre es un tipo de un paradigma de tipeo estático que quiere enterrar sus errores de JavaScript con declaraciones vacías de prueba / captura. Ha sido un fenómeno en mi experiencia. ¿Que es eso? De todos modos, no es que no recibamos comentarios cuando ejecutamos nuestro código.
Erik Reppen

Respuestas:

139

La capacidad del intérprete para deducir el tipo y las conversiones de tipo 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 puede obtener en un lenguaje estáticamente tipado donde las atrapa en tiempo de compilación. Pero cuál es mejor (o incluso si eso es siempre cierto) se discute en la comunidad en estos días (y desde hace mucho tiempo).

Un buen punto de vista sobre el tema es la escritura estática donde sea posible, la 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 escritura estática argumentan que las ventajas de la escritura estática incluyen la detección temprana de errores de programación (por ejemplo, evitar agregar un número entero a un booleano), una mejor documentación en forma de firmas de tipo (por ejemplo, incorporar números y tipos de argumentos al resolver nombres), más Oportunidades para las optimizaciones del compilador (por ejemplo, reemplazar llamadas virtuales por llamadas directas cuando se conoce estáticamente el tipo exacto del receptor), mayor eficiencia de tiempo de ejecución (por ejemplo, no todos los valores deben llevar un tipo dinámico) y una mejor experiencia del desarrollador en tiempo de diseño (por ejemplo, conocer 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 escritos 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 en tiempo de ejecución de su programa y, por lo tanto, es necesariamente solo parcialmente e incompleto. Esto significa que los programas aún pueden salir mal debido a las propiedades que no son rastreadas por el verificador de tipo, y que hay programas que, aunque no pueden salir mal, no pueden verificarse. El impulso de hacer que la escritura estática sea menos parcial y más completa hace que los sistemas de tipos se vuelvan demasiado complicados y exóticos, como lo demuestran conceptos como "tipos fantasma" [11] y "tipos tambaleantes" [10]. Esto es como tratar de correr un maratón con una pelota y una cadena atadas a la pierna y gritar triunfante que casi lo logras a pesar de que saliste después de la primera milla. La verificación de tipo estático es una abstracción en tiempo de compilación del comportamiento en tiempo de ejecución de su programa y, por lo tanto, es necesariamente solo parcialmente e incompleto. Esto significa que los programas aún pueden salir mal debido a las propiedades que no son rastreadas por el verificador de tipo, y que hay programas que, aunque no pueden salir mal, no pueden verificarse. El impulso de hacer que la escritura estática sea menos parcial y más completa hace que los sistemas de tipos se vuelvan demasiado complicados y exóticos, como lo demuestran conceptos como "tipos fantasma" [11] y "tipos tambaleantes" [10]. Esto es como tratar de correr un maratón con una pelota y una cadena atadas a la pierna y gritar triunfante que casi lo logras a pesar de que saliste después de la primera milla. La verificación de tipo estático es una abstracción en tiempo de compilación del comportamiento en tiempo de ejecución de su programa y, por lo tanto, es necesariamente solo parcialmente e incompleto. Esto significa que los programas aún pueden salir mal debido a las propiedades que no son rastreadas por el verificador de tipo, y que hay programas que, aunque no pueden salir mal, no pueden verificarse. El impulso de hacer que la escritura estática sea menos parcial y más completa hace que los sistemas de tipos se vuelvan demasiado complicados y exóticos, como lo demuestran conceptos como "tipos fantasma" [11] y "tipos tambaleantes" [10]. Esto es como tratar de correr un maratón con una pelota y una cadena atadas a la pierna y gritar triunfante que casi lo logras a pesar de que saliste después de la primera milla. y por lo tanto, es necesariamente solo parcialmente e incompleto. Esto significa que los programas aún pueden salir mal debido a las propiedades que no son rastreadas por el verificador de tipo, y que hay programas que, aunque no pueden salir mal, no pueden verificarse. El impulso de hacer que la escritura estática sea menos parcial y más completa hace que los sistemas de tipos se vuelvan demasiado complicados y exóticos, como lo demuestran conceptos como "tipos fantasma" [11] y "tipos tambaleantes" [10]. Esto es como tratar de correr un maratón con una pelota y una cadena atadas a la pierna y gritar triunfante que casi lo logras a pesar de que saliste después de la primera milla. y por lo tanto, es necesariamente solo parcialmente e incompleto. Esto significa que los programas aún pueden salir mal debido a las propiedades que no son rastreadas por el verificador de tipo, y que hay programas que, aunque no pueden salir mal, no pueden verificarse. El impulso de hacer que la escritura estática sea menos parcial y más completa hace que los sistemas de tipos se vuelvan demasiado complicados y exóticos, como lo demuestran conceptos como "tipos fantasma" [11] y "tipos tambaleantes" [10]. Esto es como tratar de correr un maratón con una pelota y una cadena atadas a la pierna y gritar triunfante que casi lo logras a pesar de que saliste después de la primera milla. y que hay programas que, si bien no pueden salir mal, no pueden verificarse por tipo. El impulso de hacer que la escritura estática sea menos parcial y más completa hace que los sistemas de tipos se vuelvan demasiado complicados y exóticos, como lo demuestran conceptos como "tipos fantasma" [11] y "tipos tambaleantes" [10]. Esto es como tratar de correr un maratón con una pelota y una cadena atadas a la pierna y gritar triunfante que casi lo logras a pesar de que saliste después de la primera milla. y que hay programas que, si bien no pueden salir mal, no pueden verificarse por tipo. El impulso de hacer que la escritura estática sea menos parcial y más completa hace que los sistemas de tipos se vuelvan demasiado complicados y exóticos, como lo demuestran conceptos como "tipos fantasma" [11] y "tipos tambaleantes" [10]. Esto es como tratar de correr un maratón con una pelota y una cadena atadas a la pierna y gritar triunfante que casi lo logras a pesar de que saliste después de la primera milla.

Los defensores de los lenguajes escritos dinámicamente argumentan que el tipeo estático es demasiado rígido, y que la suavidad de los lenguajes dinámicamente los hace ideales para prototipos de sistemas con requisitos cambiantes o desconocidos, o que interactúan con otros sistemas que cambian de manera impredecible (integración de datos y aplicaciones). Por supuesto, los lenguajes escritos dinámicamente son indispensables para lidiar con el comportamiento verdaderamente dinámico del programa, como la intercepción de métodos, la carga dinámica, el código móvil, la reflexión en tiempo de ejecución, etc. En la madre de todos los documentos sobre scripting [16], John Ousterhout argumenta que los sistemas tipados estáticamente Los lenguajes de programación hacen que el código sea menos reutilizable, más detallado, no más seguro y menos expresivo que los lenguajes de secuencias de comandos escritos dinámicamente. Este argumento es repetido literalmente por muchos defensores de los lenguajes de secuencias de comandos de escritura dinámica. Argumentamos que esto es una falacia y cae en la misma categoría que argumentar que la esencia de la programación declarativa es eliminar la asignación. O como dice John Hughes [8], es una imposibilidad lógica hacer que un lenguaje sea más poderoso al omitir características. Defender el hecho de que retrasar toda verificación de tipos en tiempo de ejecución es una buena cosa, es jugar tácticas de avestruz con el hecho de que los errores deben detectarse lo antes posible en el proceso de desarrollo. Es una imposibilidad lógica hacer que un lenguaje sea más poderoso omitiendo funciones. Defender el hecho de que retrasar toda verificación de tipos en tiempo de ejecución es una buena cosa, es jugar tácticas de avestruz con el hecho de que los errores deben detectarse lo antes posible en el proceso de desarrollo. Es una imposibilidad lógica hacer que un lenguaje sea más poderoso omitiendo funciones. Defender el hecho de que retrasar toda verificación de tipos en tiempo de ejecución es una buena cosa, es jugar tácticas de avestruz con el hecho de que los errores deben detectarse lo antes posible en el proceso de desarrollo.

Vinko Vrsalovic
fuente
37
"intercepción de métodos, carga dinámica, código móvil, reflexión en tiempo de ejecución" se puede hacer todo en Java, solo para el registro.
Will Hartung
13
Los tipos fantasmas no son "demasiado complicados".
Jon Harrop
12
El enlace al documento de Meijer está roto a partir del 16/05/2010.
jchadhowell
55
@jchadhowell, puedes encontrar eso aquí research.microsoft.com/en-us/um/people/emeijer/Papers/…
Srinivas Reddy Thatiparthy
44
@VinkoVrsalovic Los lenguajes estáticos con inferencia de tipos y polimorfismo son bastante buenos para la creación rápida de prototipos. Ofrecen la misma comodidad que el lenguaje dinámico y la seguridad de los lenguajes estáticos.
Edgar Klerks
119

Los sistemas de tipo estático buscan eliminar ciertos errores estáticamente, inspeccionando el programa sin ejecutarlo e intentando demostrar la solidez en ciertos aspectos. Algunos sistemas de tipos pueden detectar más errores que otros. Por ejemplo, C # puede eliminar las excepciones de puntero nulo cuando se usa correctamente, mientras que Java no tiene ese poder. Twelf tiene un sistema de tipos que realmente garantiza que las pruebas terminarán , "resolviendo" 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 detención, simplemente lo evita arrojando una gran cantidad de pruebas perfectamente válidas que terminan de manera extraña. Del mismo modo, el sistema de tipos de Java rechaza la PersistentVectorimplementación de Clojure 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 cual es tedioso en el mejor de los casos. Además, los lenguajes tipados estáticamente pueden tener ciertas características que son imposibles o inseguras en los sistemas de tipos dinámicos (me vienen a la mente las conversiones implícitas ). Todo es una cuestión de requisitos y gusto subjetivo. No construiría más el próximo Eclipse en Ruby de lo que trataría de escribir un script de respaldo en Assembly o parchear un kernel usando Java.

Ah, y las personas que dicen que " escribir x es 10 veces más productivo que escribir y " simplemente están echando humo. La escritura dinámica puede "sentirse" más rápido en muchos casos, pero pierde terreno una vez que realmente intentas ejecutar tu elegante aplicación . Del mismo modo, la escritura estática puede parecer la red de seguridad perfecta, pero un vistazo a algunas de las definiciones de tipo genérico más complicadas en Java hace que la mayoría de los desarrolladores se apresuren a usar anteojeras. Incluso con sistemas de tipos y productividad, no hay bala de plata.

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 acercan peligrosamente al rendimiento del lenguaje estático. Además, el hecho de que Java realmente se compila en un lenguaje intermedio intrínsecamente dinámico debería ser un indicio de que, en la mayoría de los casos, la escritura dinámica no es el gran factor que mata el rendimiento que algunas personas creen que es.

Daniel Spiewak
fuente
55
Sobre el rendimiento. En casos comunes, no hará mucha diferencia, pero en matemáticas de alta tensión y tal, hay una diferencia real. Las pruebas han demostrado una llamada de una función, en el caso de ipy vs C #, difiere con mil ciclos. Solo porque el primero tiene que estar seguro de que existe un método.
Dykam
29
¿Puede explicar el punto "C # puede eliminar las excepciones de puntero nulo cuando se usa correctamente, mientras que Java no tiene tal poder". ? Un ejemplo o cita sería muy apreciada.
Srinivas Reddy Thatiparthy
13
"algunas de las definiciones de tipo genérico más complicadas en Java envían a la mayoría de los desarrolladores a buscar anteojeras" - si este es su peor ejemplo, obviamente no ha usado C ++ ;-)
bacar
3
"Además, el hecho de que Java realmente se compila en un lenguaje intermedio intrínsecamente dinámico debería ser una pista de que, en la mayoría de los casos, la escritura dinámica no es el gran factor decisivo que algunas personas creen que es". - cuando su ejemplo de un lenguaje con "buen rendimiento" es Java, es posible que desee reconsiderarlo.
Yakk - Adam Nevraumont
" Java se compila en un intermediario intrínsecamente dinámico ", que no entiende el punto. Las comprobaciones estáticas se han realizado de antemano y, por lo tanto, no se requieren comprobaciones de tiempo de ejecución adicionales que las cubran, ya que el compilador elige instrucciones como daddporque sabe de antemano que los operandos son doubles.
Michael Beer
45

Bueno, ambos son muy, muy, muy mal entendidos y también dos cosas completamente diferentes. que no son mutuamente excluyentes .

Los tipos estáticos son una restricción de la gramática del lenguaje. Se puede decir estrictamente que los idiomas escritos estáticamente no están libres de contexto. La simple verdad es que resulta inconveniente expresar un lenguaje sensato en gramáticas libres de contexto que no tratan todos sus datos simplemente como vectores de bits. Los sistemas de tipo estático son parte de la gramática del lenguaje, si lo hay, simplemente lo restringen más de lo que podría hacerlo una gramática libre de contexto, por lo que las verificaciones gramaticales ocurren en dos pasos sobre la fuente realmente. Los tipos estáticos corresponden a la noción matemática de la 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 los tipos.

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

El problema con esto es que un sistema de tipos no puede decidir si tales operaciones van a ocurrir o no, si se permitiría su ejecución. Como en, particione exactamente el conjunto de todos los programas posibles en aquellos que van a tener un 'error de tipo' y aquellos que no. Solo puede hacer dos cosas:

1: probar que los errores de tipo van a ocurrir en un programa
2: probar que no van a ocurrir en un programa

Puede parecer que me estoy contradiciendo. Pero lo que hace un verificador de tipo C o Java es que rechaza un programa como 'no gramatical', o como lo llama 'error de tipo' si no puede tener éxito en 2. No puede probar que no van a ocurrir, eso no significa que no van a ocurrir, solo 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 simple ejemplo siendoif(1) a = 3; else a = "string";, seguramente ya que 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 tipados estáticamente, para protegerte contra ti mismo, necesariamente también estás protegido en caso de que no lo necesites.

Pero, contrariamente a la creencia popular, también hay lenguajes estáticamente tipados que funcionan según el principio 1. Simplemente rechazan todos los programas de los que pueden demostrar que causará un error de tipo y pasan todos los programas que no pueden. Por lo tanto, es posible que permitan programas que tengan errores de tipo, un buen ejemplo es Typed Racket, es híbrido entre tipeo dinámico y estático. Y algunos dirían que obtienes lo mejor de ambos mundos en este sistema.

Otra ventaja del tipeo estático es que los tipos se conocen en tiempo de compilación y, por lo tanto, el compilador puede usar esto. Si en Java hacemos "string" + "string"o 3 + 3, ambos +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 conmigo: el 'tipeo dinámico' no existe .

Sonidos muy polémicos, pero es cierto, lenguajes dinámicamente se escriben desde una perspectiva teórica sin tipo . Son solo idiomas de tipo estático con un solo tipo. O simplemente, son lenguajes que en realidad son gramaticalmente generados por una gramática libre de contexto en la práctica.

¿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 hacer lo print("string")que imprime una cadena es una operación, entonces lo es length(3), la primera tiene el efecto secundario de escribir stringen la salida estándar, la segunda simplemente error: function 'length' expects array as argument., eso es todo. Desde una perspectiva teórica, no existe un lenguaje de tipo dinámico. No están tipificados

Muy bien, la ventaja obvia del lenguaje 'tipado 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 idiomas con un sistema de tipos de hecho tendrían un resultado definido para todas aquellas operaciones que no están permitidas si el sistema de tipos simplemente se ignora, los resultados simplemente no tendrían sentido para los humanos. Muchos idiomas pierden su integridad de 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 de esto, los lenguajes escritos dinámicamente suelen redefinir esas operaciones, en lugar de producir ese resultado absurdo, lo redefinen para tener 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. 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, la razón por lo que se haceSuceder también puede ser útil en algunos puntos para la depuración, lo que demuestra que no es un "error" en absoluto, sino una propiedad bien definida del lenguaje. En efecto, el remanente único de 'tipeo dinámico' que tienen la mayoría de los idiomas está protegiendo contra una división por cero. Esto es lo que es la tipificación dinámica, no hay tipos, no hay más tipos que ese cero es un tipo diferente que todos los demás números. Lo que la gente llama 'tipo' es solo otra propiedad de un dato, como la longitud de una matriz o el primer carácter de una cadena. Y muchos idiomas escritos dinámicamente también le permiten escribir cosas como "error: the first character of this string should be a 'z'".

Otra cosa es que los idiomas escritos dinámicamente tienen el tipo disponible en tiempo de ejecución y, por lo general, pueden verificarlo, manejarlo 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 de qué se trata. De hecho, puede hacer su propia C dinámica, solo use un tipo como long long int y use los primeros 8 bits para almacenar su 'tipo' y escribir funciones en consecuencia que lo comprueben y realicen la suma flotante o entera. Tiene un idioma de tipo estático con un tipo o un idioma dinámico.

En la práctica, todo esto muestra que los lenguajes tipados estáticamente se usan generalmente en el contexto de la escritura de software comercial, mientras que los lenguajes tipados dinámicamente tienden a usarse en el contexto de resolver algunos problemas y automatizar algunas tareas. Escribir código en idiomas estáticamente escritos simplemente lleva mucho tiempo y es engorroso porque no puede hacer cosas que sabe que van a salir bien, pero el sistema de tipos aún lo protege contra usted mismo por errores que no comete. Muchos programadores ni siquiera se dan cuenta de que lo hacen 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 permite hacer cosas que no pueden salir mal, porque No puedo demostrar que no saldrá mal.

Como señalé, "tipificado estáticamente" en general significa el 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, utilizan la regla 1: Inocente hasta que se pruebe su culpabilidad, que podría ser el híbrido ideal. Entonces, tal vez Typed Racket es 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 es en sí mismo un tipo y dato, el único dato que se tiene a sí mismo como tipo. Los tipos no son finitos o están limitados estáticamente, pero se pueden generar nuevos tipos en función de la información de tiempo de ejecución.

Zorf
fuente
1
"Muchos idiomas pierden su integridad de Turing después de aplicar un sistema de tipos". no se aplica a los lenguajes de programación habituales, ¿verdad? por lo que leo, los idiomas normales no están completos
Răzvan Flavius ​​Panda
1
@ RăzvanPanda: Lajla probablemente se estaba refiriendo a variaciones en el cálculo lambda tipificado o en algunos de los lenguajes de programación que usan en los probadores de teoremas. Muchos de ellos solo pueden expresar programas que están garantizados para detenerse y, por lo tanto, no están completos. Los lenguajes de programación funcionales prácticos basados ​​en estos sistemas de tipos superan esta limitación al extender el cálculo central con tipos recursivos.
hugomg
1
"Suena muy controvertido, pero es cierto, los lenguajes escritos dinámicamente no están tipificados desde una perspectiva teórica". - ... y, en un instante, sé que no tienes idea de lo que estás hablando. La escritura dinámica solo significa que los tipos pertenecen a los valores, no a los identificadores. Hace que los programas sean más difíciles de probar, pero no necesariamente imposibles. El polimorfismo en línea y paramétrico ya ha llevado al desarrollo de la optimización del tiempo de enlace; que resuelve el mismo tipo de problema que tiene la compilación de lenguajes óptimos de tipo dinámico: conocer todas las entradas y salidas posibles.
DeftlyHacked
25

Quizás el mayor "beneficio" del tipeo dinámico es la curva de aprendizaje más superficial. No hay un sistema de tipos para aprender y no hay sintaxis no trivial para casos de esquina como restricciones de tipo. Eso hace que la escritura dinámica sea accesible para muchas más personas y sea factible para muchas personas para quienes los sistemas sofisticados de tipo estático están fuera del alcance. En consecuencia, la escritura dinámica se ha popularizado en los contextos de educación (por ejemplo, Scheme / Python en el MIT) y lenguajes específicos de dominio para no programadores (por ejemplo, Mathematica ). Los lenguajes dinámicos también se han popularizado en nichos donde tienen poca o ninguna competencia (por ejemplo, Javascript).

Los lenguajes de tipo dinámico más concisos (por ejemplo, Perl, APL, J, K, Mathematica ) son específicos del dominio y pueden ser significativamente más concisos que los lenguajes de tipo estático con fines generales más concisos (por ejemplo, OCaml ) en los nichos para los que fueron diseñados. .

Las principales desventajas del tipeo dinámico son:

  • Errores de tipo en tiempo de ejecución.

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

  • No hay documentación verificada por el compilador.

  • Rendimiento deficiente (generalmente en tiempo de ejecución pero a veces en tiempo de compilación, por ejemplo, Esquema de Stalin) y rendimiento impredecible debido a la dependencia de optimizaciones sofisticadas.

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

Jon Harrop
fuente
2
Diría que la barrera de entrada es menor, pero el dominio no es menos una curva de aprendizaje.
Erik Reppen
¿No es menos la curva de aprendizaje porque no tienes un sistema de tipos para aprender?
Jon Harrop
Todavía hay un sistema de tipos. Puede hacer conjeturas razonables sobre lo que sucede cuando agrega un bool y una cadena, pero a menudo ayuda mucho conocer algunos detalles reales de cómo se coaccionan los tipos en un lenguaje de tipo dinámico. Eso es lo que mucha gente estrictamente estricta no entiende. De hecho, aprendemos estas cosas.
Erik Reppen
@ErikReppen: Estamos utilizando diferentes definiciones de "sistema de tipos". Me refería a no tener que aprender un sistema de tipo estático, por ejemplo, tipos de datos algebraicos, genéricos. Los "tipos" a los que se refiere son solo datos. El hecho de que algunas funciones rechacen algunos datos en tiempo de ejecución es universal.
Jon Harrop
12

Del artículo de Artima's Typing: Strong vs. Weak, Static vs. Dynamic :

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

la escritura débil significa que puede mezclar tipos sin una conversión explícita

En el artículo de Pascal Costanza, Dynamic vs. Static Typing - A Pattern-Based Analysis (PDF), afirma que en algunos casos, la escritura estática es más propensa a errores que la escritura dinámica. Algunos lenguajes tipados estáticamente te obligan a emular manualmente el tipeo dinámico para hacer "Lo correcto". Se discute en Lambda the Ultimate .

Mark Cidade
fuente
1
"la escritura estática es más propensa a errores que la escritura dinámica" - Sí, sí, y DOBLE ¡sí! He tenido mucha experiencia en ambos tipos de lenguajes, y en todos los casos el lenguaje dinámico "simplemente funciona" mientras que el estático requiere el doble de tiempo de depuración (Ver C ++ y Delphi). Esto se debe con frecuencia a problemas de tipo, especialmente al pasar datos entre módulos y funciones con tipos locos. Aunque hay todo tipo de errores teóricos, los lenguajes dinámicos supuestamente pueden causar, en la práctica, es MUY raro que me encuentre con un error causado por la coerción de tipo, a menos que sea un programador pobre que abusa de los tipos dinámicos.
dallin
77
Leí un borrador del artículo de Costanza hace unos años. En todas partes había escrito "estático", realmente quería decir específicamente "Java". Le di docenas de contraejemplos en idiomas como OCaml que refutaban sus afirmaciones, pero siguió adelante y lo publicó de todos modos. Por el aspecto de ese periódico, todavía está publicando las mismas tonterías de siempre. Por ejemplo, en ese documento afirma que "C # es generalmente una mala copia de Java". Eso no tiene cabida en un artículo científico ...
Jon Harrop
@dallin mi experiencia es todo lo contrario: tener que programar mucho en C, C ++, Java, Python, Perl y similares, nunca comenzaría algo más grande que un pequeño programa de ajustes en un lenguaje de tipo dinámico a menos que sea forzado. En Python, todavía tiemblo al pensar en un proyecto WSGI: las devoluciones de llamada que tuve que sobrescribir se pasaron en referencias de objetos, y el código pareció funcionar bien, cuando se bloqueó porque resultó que a veces no son objetos, sino algunos tipos elementales siendo aprobado Un lenguaje que hace que sea fácil crear cosas con errores como ese es directamente peligroso.
Michael Beer
@MichaelBeer También podría decir que un lenguaje como C / C ++ que le permite administrar directamente la memoria es directamente peligroso. Ciertamente he luchado con errores de memoria durante horas. Los enormes proyectos Java tampoco son un picnic. En cualquier idioma, debe comprender los peligros del idioma y las buenas prácticas. Los peores proyectos en los que he trabajado fueron proyectos PHP en equipo con poca estructura, pero también trabajé en proyectos con lenguajes dinámicos que eran un sueño cuando usaban un buen marco y buenas prácticas de programación.
dallin
@dallin De acuerdo, cada idioma tiene sus trampas. Pero las fallas a las que me referí son inherentes a cualquier lenguaje de tipo dinámico, la posibilidad de manipular la memoria directamente no es una propiedad inherente de los idiomas de tipo estático. Puedes imaginar lenguajes escritos dinámicamente que te permiten manipular mem directamente. Estoy de acuerdo en que C ++ es un desastre directo, ya que el inventor del lenguaje mismo cree que ni una sola persona en este planeta puede conocer todas las partes del lenguaje. Sin embargo, esto no se puede culpar a que C ++ se tipee estáticamente, sino a un monstruo que ha estado creciendo desde hace 30 años ...
Michael Beer,
3

Depende del contexto. Hay muchos beneficios que son apropiados para el sistema de tipo dinámico, así como para el 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 los atributos de clase y el compilador pensando en lo que está sucediendo en el código. Tienes un poco de libertad. Además, el lenguaje dinámico generalmente es más expresivo y da como resultado 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 lang dinámico, pero el mantenimiento puede convertirse en una pesadilla.

La principal ganancia sobre el sistema de tipo estático es el soporte IDE y seguramente el analizador de código estático. Te vuelves más seguro del código después de cada cambio de código. El mantenimiento es sencillo con tales herramientas.

AndrewG
fuente
0

Hay muchas cosas diferentes sobre los lenguajes estáticos y dinámicos. Para mí, la principal diferencia es que en 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 es indeterminado hasta el tiempo de ejecución.

En implementaciones tempranas o ingenuas, este es un gran obstáculo para el rendimiento, pero los JIT modernos se acercan tentadoramente a lo mejor que puede obtener con la optimización de compiladores estáticos. (en algunos casos marginales, incluso mejor que eso).

Javier
fuente
0

Se trata de la herramienta adecuada para el trabajo. Tampoco es mejor el 100% del tiempo. 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 sale 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 enloquece a un programador novato (en lenguajes escritos) que intenta enloquecer entre un char constante y una cadena.

JJ
fuente
-3

Escritura Estática: los lenguajes como Java y Scala son de escritura estática.

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

por ej. int x; x = 10;

System.out.println (x);

Typing Dinámico: Perl es un lenguaje de escritura dinámica.

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

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

Prakhyat
fuente
55
Esto no tiene nada que ver con el sistema de tipos.
Thiago Negri