Contactos

Typing dinámico. Likbez escribiendo en lenguajes de programación La escritura dinámica es mejor que estricta

Este artículo contiene el mínimo necesario de aquellas cosas que solo necesita saber sobre la escritura, para no llamar la escritura dinámica por el mal, el LISP es un idioma tetonoso y el lenguaje C con estricto tipificación.

En la versión completa hay una descripción detallada de todos los tipos de escritura, sazonados con ejemplos de código, referencias a lenguajes de programación populares y imágenes explícitas.

Recomiendo leer primero una breve versión del artículo y luego con deseo y completo.

Versión breve

Las lenguas de programación de la tipificación se realizan para dividir en dos campamentos grandes, mecanografiados y no tipo (tetona). A la primera, por ejemplo, C, Python, Scala, PHP y LUA incluyen, y el segundo es el lenguaje del ensamblador, hacia atrás y el cerebro.

Dado que "la tipificación convencional" es intrínsecamente simple como un atasco de tráfico, entonces no se divide en ninguna otra especie. Pero las lenguas escritas se dividen en varias otras categorías de intersección:

  • Escribir estático / dinámico. Estática está determinada por el hecho de que los tipos finales de variables y funciones se establecen en la etapa de compilación. Esos. Ya el compilador está 100% seguro de qué tipo se encuentra donde se encuentra. En la escritura dinámica, ya se encuentran todos los tipos durante la ejecución del programa.

    Ejemplos:
    Estático: C, Java, C #;
    Dinámico: Python, JavaScript, Ruby.

  • Tymificación fuerte / débil (también a veces dice estricto / no golpeado). El hecho de que la escritura fuerte se asigna por el hecho de que el idioma no le permite mezclar diferentes tipos en expresiones y no implica automáticamente las conversiones, por ejemplo, no puede deducir desde el conjunto de cadenas. Los idiomas con tipificación débil realizan una variedad de transformaciones implícitas automáticamente, incluso si la pérdida de precisión o la conversión pueden ocurrir en ambigüedad.

    Ejemplos:
    Fuerte: Java, Python, Haskell, Lisp;
    Débil: C, JavaScript, Visual Basic, PHP.

  • Tipificación explícita / implícita. Los idiomas escritos explícitos se distinguen por el hecho de que el tipo de nuevas variables / funciones / sus argumentos debe especificarse explícitamente. En consecuencia, las lenguas con la tipificación implícita cambian esta tarea en el compilador / intérprete.

    Ejemplos:
    Explícito: C ++, D, C #
    Implícito: PHP, LUA, JavaScript

También se debe tener en cuenta que todas estas categorías intersectan, por ejemplo, el idioma C tiene una tipificación explícita estática y estática, y el lenguaje de Python es una fuerte implícita dinámica.

Sin embargo, no menos que los idiomas de las tipias estáticas y dinámicas al mismo tiempo. A pesar de correr adelante, diré que estoy aquí, realmente existen, pero al respecto más tarde.

Versión detallada

Si una breve versión no parecía suficiente, buena. ¿No es de extrañar que escribiera un detallado? Lo principal es que en una breve versión fue simplemente imposible de adaptarse a toda la información útil e interesante, y los detalles serían demasiado largos que todos pudieran leerlo, no se esforzan.

Tipificación básica

En los lenguajes de programación de pechos, todas las entidades se consideran simplemente secuencias de bits, diferentes longitudes.

La tipificación Bestipa es generalmente inherente a los idiomas de bajo nivel (ensamblador,) y esotérico (Brainfuck, HQ9, PIET). Sin embargo, ella, junto con las desventajas, tienen algunas ventajas.

Beneficios
  • Le permite escribir en un nivel máximo bajo, y el compilador / intérprete no interferirá con ningún tipo de tipos. Usted es libre de producir cualquier operación en cualquier tipo de datos.
  • El código resultante suele ser más eficiente.
  • Transparencia de las instrucciones. Con el conocimiento del idioma, generalmente no hay duda de que uno u otro código representa.
desventajas
  • Complejidad. A menudo, existe la necesidad de presentar valores integrales, como listas, filas o estructuras. Puede haber inconvenientes.
  • No hay cheques. Cualquier acción sin sentido, como la resta de un puntero a una matriz del símbolo, se considerará completamente normal, lo que está lleno de errores de empleo.
  • Baja abstracción. Trabajar con cualquier tipo de datos complejo no es diferente de trabajar con números, que, por supuesto, creará muchas dificultades.
¿Fuerte tipificación espinosa?

Sí, existe. Por ejemplo, en el idioma del ensamblador (para la arquitectura X86 / X86-64, no conozco a los demás), no puede ensamblar el programa si intenta cargar en los datos del Registro CX (16 bits) desde el registro RAX (64 bits ).

mOV CX, EAX; Error tiempo de montaje

¿Así que resulta que todavía está escribiendo en el assemor? Creo que estos controles no son suficientes. Y tu opinión, por supuesto, depende solo de ti.

Tyming estático y dinámico.

Lo principal es que distingue a la escritura estática (estática) de la dinámica (dinámica) que todos los tipos de tipos se realizan en la etapa de compilación, no la etapa de ejecución.

Algunas personas pueden parecer que la escritura estática es demasiado limitada (de hecho, es, pero durante mucho tiempo ha estado deshaciéndose de algunos métodos). De la misma manera que los idiomas tipificados dinámicamente son un juego con fuego, pero ¿qué características están asignadas? ¿Ambas especies tienen la probabilidad de existencia? Si no, ¿por qué hay muchos más que idiomas estáticamente y tipificados dinámicamente?

Vamos a resolverlo.

Beneficios de la escritura estática.
  • Los cheques de tipo ocurren solo una vez, en la etapa de compilación. Y esto significa que no tendremos que descubrir constantemente si estamos tratando de dividir el número en la cadena (y dar el error o transformar).
  • Velocidad de rendimiento. Se desprende del punto anterior que los idiomas que mecanografiados estáticamente son casi siempre más rápidos que las tipificadas dinámicamente.
  • Con algunas condiciones adicionales, le permite detectar potenciales errores en la etapa de compilación.
Ventajas de la escritura dinámica.
  • Fácil de crear colecciones universales: un grupo de todos y todos (rara vez surge esa necesidad, pero cuando la escritura dinámica surge para ayudar).
  • Facilidad de describir algoritmos generalizados (por ejemplo, clasificar una matriz que funcionará no solo en la lista de enteros, sino también en la lista de reales e incluso en la lista de líneas).
  • Fácil en desarrollo: los idiomas con tipilación dinámica suelen ser muy buenos para comenzar la programación.

Programación generalizada

Bueno, el argumento más importante para la escritura dinámica es la conveniencia de describir algoritmos generalizados. Imaginemos un problema: necesitamos una función de búsqueda para varias matrices (o listas), por la matriz de enteros, de acuerdo con la matriz de los personajes real y la matriz.

¿Cómo lo resolveremos? Lo resuelvo en los 3º lenguajes diferentes: uno con tipificación dinámica y dos con estática.

Buscar algoritmo Tomaré uno de los más simples. La función recibirá el elemento deseado, la matriz en sí (o la lista) y devolverá el índice del elemento, o si el elemento no se encuentra - (-1).

Solución dinámica (Python):

DEF Buscar (Requery_Element, LISTA): para (índice, elemento) en enumeración (lista): if element \u003d\u003d requerido_element: retorno del índice de retorno (-1)

Como puede ver, todo es simple y no hay problema con el hecho de que la lista pueda contener al menos números, aunque no haya otras matrices. Muy bien. Vamos a seguir - ¡Decide esta tarea en C!

Solución estática (C):

INTSIGNED IND Find_int (INT PEDIDE_ELEMENT, INT ARRAY, TAMAÑO DE INT sin firmar) (para (no firmado int i \u003d 0; i< size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_float(float required_element, float array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_char(char required_element, char array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); }

Bueno, cada función es individualmente similar a la versión de Python, pero ¿por qué hay tres? ¿Es realmente la programación estática?

Si y no. Hay varias técnicas de programación, una de las cuales ahora consideramos. Se llama programación generalizada y el lenguaje C ++ lo apoya bien. Veamos la nueva versión:

Solución estática (programación generalizada, C ++):

Plantilla. INT no firmado Encuentre (T Requiry_Element, Std :: Vector matriz) (por insignificada int i \u003d 0; i< array.size(); ++i) if (required_element == array[i]) return i; return (-1); }

¡Okey! No parece mucho más difícil que la versión en Python y, al mismo tiempo, no tuvo que escribir mucho. Además, obtuvimos la implementación para todas las matrices, ¡y no solo por la tercera vez necesaria para resolver el problema!

Esta versión parece ser exactamente lo que necesita: obtenemos al mismo tiempo las ventajas de la escritura estática y algunas ventajas son dinámicas.

Es genial que generalmente sea posible, pero tal vez incluso mejor. Primero, la programación generalizada puede ser más conveniente y más hermosa (por ejemplo, en Haskell). En segundo lugar, además de la programación generalizada, también es posible aplicar un polimorfismo (el resultado será peor), la sobrecarga de funciones (de manera similar) o macros.

Estadísticas en Dinámica

También es necesario mencionar que muchos idiomas estáticos le permiten usar la escritura dinámica, por ejemplo:

  • C # admite dinámica de tipo pseudo.
  • F # ¡Admite el azúcar de sintaxis en forma de operador?, Sobre la base de la cual se puede implementar la imitación de la escritura dinámica.
  • Haskell: la escritura dinámica es proporcionada por el módulo Data.Dynamic.
  • Delphi - a través de un tipo especial de variante.

Además, algunos idiomas tipificados dinámicamente le permiten aprovechar la escritura estática:

  • Declaración de tipos de lisp común.
  • Perl - de la versión 5.6, bastante limitado.

Typisius fuerte y débil

Los idiomas con una escritura fuerte no permiten mezclar la esencia de diferentes tipos en expresiones y no realizar ninguna transformación automática. También se llaman "Idiomas con estricto mecanografía". Término inglés para esto - fuerte mecanografía.

Idiomas débiles tipificados, por el contrario, en plena grasa, de modo que el programador mezcle diferentes tipos en una expresión, y el propio compilador resultará en un solo tipo. También llaman "idiomas con tipificación no inicial". El término en inglés para esto es una escritura débil.

La tipificación débil a menudo se confunde con dinámica, que es completamente incorrecta. Un lenguaje tipificado dinámicamente puede ser débil y fuertemente escrito.

Sin embargo, pocos que adjuntan el valor del rigor de la escritura. A menudo se afirma que si el idioma está escrito estáticamente, puede capturar muchos errores potenciales al compilar. ¡Te mienten!

El idioma debe tener más y fuerte mecanografía. Y la verdad, si el compilador, en lugar de un mensaje de error, simplemente agregará una fila a un número, o lo que es aún peor, la deducción de un macizo es otro, ¿cuál es el uso de los tipos que todos los "cheques" estar en la etapa de compilación? ¡Eso es correcto: la escritura estática débil es aún peor que la fuerte dinámica! (Bueno, esta es mi opinión)

Entonces, ¿qué pasa con el débil TypiSius no tiene suficiente más? Tal vez se vea así, pero a pesar del hecho de que debería estar de acuerdo con un partidario exhaustivo de la escritura fuerte, también tiene ventajas.

¿Quieres saber qué?

Beneficios de la fuerte mecanografía.
  • Fiabilidad: obtendrá una excepción o error de compilación, en lugar de un comportamiento incorrecto.
  • Velocidad: en lugar de transformaciones ocultas que pueden ser bastante caras, con una escritura fuerte, es necesario escribirlas claramente, lo que hace que un programador al menos sepa que esta sección del código puede ser lenta.
  • Comprender el trabajo del programa: nuevamente, en lugar de los tipos impregnados de tipos, el programador lo escribe todo mismo, lo que significa que entiende aproximadamente que la comparación de la cadena y el número no sucede por sí mismo.
  • Nota: cuando escribe la conversión manualmente, sabe exactamente lo que se convierte y qué. También siempre entenderá que tales transformaciones pueden llevar a la pérdida de precisión y los resultados incorrectos.
Las ventajas de la escritura débil.
  • Facilidad de uso de expresiones mixtas (por ejemplo, de enteros y números reales).
  • Abstracción de escribir y enfocarse en la tarea.
  • Breve grabación.

¡Está bien, lo descubrimos, también resulta tener una tipificación débil, ¡hay ventajas! ¿Hay alguna forma de mover los pros de la tipificación débil en fuerte?

Resulta que incluso dos.

Aclaración implícita de los tipos, en situaciones inequívocas y sin pérdida de datos.

Wow ... un artículo bastante largo. Permítanme continuar cortándolo a la "transformación implícita limitada", entonces, ¿qué significa la situación inequívoca y la pérdida de datos?

Una situación inequívoca es una transformación o una operación en la que se entiende inmediatamente la esencia. Por ejemplo, la adición de dos números es una situación inequívoca. Y la transformación del número en una matriz no es (es posible crear una matriz de un elemento, posiblemente una matriz, con elementos predeterminados, y el número se puede convertir en la cadena y luego en la cadena. Una matriz de caracteres).

La pérdida de datos es aún más fácil. Si convierte un número real 3.5 a la totalidad, perderemos parte de los datos (de hecho, esta operación también es ambigua: ¿cómo se redondeará? ¡También? De una manera más pequeña? ¿Cae la parte fraccional?).

Las transformaciones en situaciones ambiguas y la conversión con pérdida de datos son muy, muy mal. No hay nada peor en la programación.

Si no me cree, aprenda el idioma PL / I o simplemente busque su especificación. ¡Tiene reglas para la transformación entre todo tipo de datos! ¡Es el infierno!

De acuerdo, recordemos la conversión implícita limitada. ¿Hay tales idiomas? Sí, por ejemplo, en Pascal, puede convertir un entero en uno real, pero no viceversa. También se encuentran mecanismos similares en C #, maravilloso y lisp común.

Bueno, dije que todavía hay una manera de obtener un par de ventajas de la tipificación débil en un lenguaje fuerte. Y sí, es y llamado el polimorfismo de los diseñadores.

Lo explicaré en el ejemplo de una lengua maravillosa Haskell.

Los diseñadores polimórficos aparecieron como resultado de la observación, que a menudo se necesitan transformaciones seguras implícitas cuando se utilizan literales numéricos.

Por ejemplo, en la expresión PI + 1, no quiero escribir PI + 1.0 o PI + FLOAT (1). ¡Quiero escribir solo Pi + 1!

Y esto se hace en Haskell, debido al hecho de que el literal 1 no tiene un tipo específico. Esto no es ni ni real ni complejo. ¡Es solo un número!

Como resultado, al escribir una función de suma simple XY, moviendo todos los números de x a y (con incremento en 1), obtenemos varias versiones: suma para enteros, suma de real, suma para racional, suma para números complejos e incluso suma Para todos estos tipos numéricos que ellos mismos han identificado.

Por supuesto, esta recepción se guarda solo cuando se usa expresiones mixtas con literales numéricos, y esto es solo la parte superior del iceberg.

Por lo tanto, se puede decir que la mejor salida se equilibrará por el borde, entre la escritura fuerte y débil. Pero si bien el equilibrio perfecto no tiene ningún idioma, por lo que estoy más inclinado a los idiomas tipificados fuertemente (como Haskell, Java, C #, Python), y no se escribió débilmente (como C, JavaScript, Lua, PHP).

Tipificación explícita e implícita.

El idioma con la tipificación explícita asume que el programador debe especificar los tipos de todas las variables y funciones que anuncian. Término de inglés para esto: escribiendo explícito.

El idioma con la tipificación implícita, por el contrario, le ofrece a olvidarse de los tipos y cambiar la tarea de emitir tipos al compilador o intérprete. Término de inglés para esto - tipificación implícita.

Al principio, es posible decidir que la escritura implícita es equivalente a la dinámica, y explícitamente estática, pero luego veremos que no lo es.

¿Hay alguna ventaja de cada especie, y nuevamente, hay alguna combinación y hay idiomas con el apoyo de ambos métodos?

Ventajas de la tipificación explícita.
  • La presencia de la función de firma (por ejemplo, INT ADD (INT, INT)) le permite determinar sin ningún problema que haga la función.
  • El programador escribe inmediatamente cómo se puede almacenar el tipo de valor en una variable específica, que elimina la necesidad de memorizarla.
Las ventajas de la escritura implícita.
  • RECUERDO REDUCCIÓN: DEF Agregar (X, Y) es claramente más corta que int x, int y).
  • Resistencia a los cambios. Por ejemplo, si la función de variable temporal fue del mismo tipo que el argumento de entrada, luego en un lenguaje escribido explícitamente cuando se cambia el tipo de argumento, también se cambiará el tipo de variable temporal.

Bueno, se puede ver que ambos enfoques tienen tanto los pros y los contras (¿y quién esperaba algo más?), ¡Así que vamos a encontrar maneras de combinar estos dos enfoques!

Tipificación explícita

Hay idiomas, con una tipificación implícita del valor predeterminado y la capacidad de especificar el tipo de valores si es necesario. Este tipo de traductor de expresión se mostrará automáticamente. Uno de estos idiomas es Haskell, déjame dar un ejemplo simple, para mayor claridad:

Sin especificar explícitamente el tipo agregado (x, y) \u003d x + y: indicación explícita del tipo ADD :: (entero, entero) -\u003e Integer Agregar (x, y) \u003d x + y

Nota: Tenía la intención de usar una función no marcada, y también tiene la intención de registrar una firma privada en lugar de agregar más general :: (NUM A) -\u003e A -\u003e A -\u003e A, porque Quería mostrar la idea, sin explicar la sintaxis de Haskell "a.

mmm Como vemos, es muy bonito y corto. ¡El registro de funciones solo toma 18 caracteres en una línea, incluidos los espacios!

Sin embargo, la salida automática de los tipos es algo bastante complejo, e incluso en un lenguaje tan fresco como Haskell, a veces no lo hace frente. (Como ejemplo, se puede obtener el límite del monomorfismo)

¿Hay idiomas con la tipificación explícita de la necesidad predeterminada e implícita? Kon
eULY.

Tipificación implícita

En el nuevo estándar de lenguaje C ++ llamado C ++ 11 (anteriormente llamado C ++ 0x), se ingresó la palabra clave automática, gracias a la que puede hacer la salida del compilador, según el contexto:

Comparemos: // Indicación manual del tipo insinenciado INT A \u003d 5; insigned int b \u003d a + 3; // Salida automática del tipo insinenciado INT A \u003d 5; AUTO B \u003d A + 3;

No está mal. Pero el registro no se redujo mucho. Veamos un ejemplo con los iteradores (si no lo entiende, no tenga miedo, lo principal es notar que la grabación está muy reducida por la conclusión automática):

// Indicación manual Tipo STD :: Vector Vec \u003d RandomVector (30); Para (std :: vector :: const_terator It \u003d vec.cbegin (); ...) (...) // Salida automática de tipo AUTO VEC \u003d RandomVector (treinta); Para (AUTO IT \u003d VEC.CBEGIN (); ...) (...)

¡Guau! Esta es una reducción. De acuerdo, pero ¿es posible hacer algo en el Espíritu Haskell, donde el tipo de valor de retorno dependerá de los tipos de argumentos?

Y nuevamente, la respuesta es sí, gracias a la palabra clave DectType en combinación con Auto:

// Indicación manual del tipo INT Divide (int x, int y) (...) // Salida automática del tipo AUTO DIVIDE (INT X, INT Y) -\u003e DeclType (X / Y) (...)

Puede parecer que esta forma de grabación no es muy buena, pero en combinación con la programación generalizada (plantillas / genéricos), la escritura implícita o la salida automática de los tipos están creando maravillas.

Algunos idiomas de programación para esta clasificación.

Le daré una pequeña lista de idiomas populares y escribiré cómo están divididos por cada categoría de "tipesaciones".

JavaScript - Rubí dinámico / débil / implícito - Python dinámico / severo / implícito - Dinámico / severa / implícita Java - estática / severa / explícita PHP - Dinámico / débil / implícito C - estática / débil / explícito C ++ - estática / semi- SYL / Explícit PERL - Dinámico / débil / implícito Objetivo-C - estático / débil / explícito C # - Hastatrico / severo / explícito Haskell - estático / fuerte / implícito Lisp común - Dinámico / severa / implícito

Tal vez me equivoqué en algún lugar, especialmente con CL, PHP y OBJ-C, si tiene una opinión diferente en cualquier idioma, escriba en los comentarios.

Conclusión

Bueno. Pronto será ligero y siento que no hay nada más sobre la tipificación. ¿Oh, cómo? Tema sin fondo? ¿Hay muchos poco confiables? Pregunto en los comentarios, comparta información útil.



Este artículo cuenta sobre la diferencia entre las lenguas escritas y tipificadas dinámicamente estáticamente, considera los conceptos de escritura "fuerte" y "débil", y compara el poder de los sistemas de escritura en diferentes idiomas. Recientemente, se observa un movimiento claro hacia sistemas de tipificación más estrictos y potentes en la programación, por lo que es importante entender lo que estamos hablando cuando hablan de tipos y tipificación.



El tipo es una colección de valores posibles. Un entero puede poseer los valores de 0, 1, 2, 3, y así sucesivamente. Booleano puede ser verdadero o falso. Puede llegar a su tipo, por ejemplo, el tipo "Daipe", en el que son posibles los valores de "dar" y "5", y nada más. Esta no es una cadena y no es un número, es una nueva, un tipo separado.


Idiomas estáticamente escritos en el límite de los tipos de variables: el lenguaje de programación puede saber, por ejemplo, que x es un entero. En este caso, el programador está prohibido hacer x \u003d verdadero, será un código incorrecto. El compilador se negará a compilarlo, de modo que ni siquiera podamos ejecutar un código de este tipo. Otro idioma estáticamente escrito puede tener otras capacidades expresivas, y no los tipos de tipos populares pueden expresar nuestro tipo de buceo (pero muchos pueden expresar otras ideas más sofisticadas).


Los valores de la marca de lenguajes tipificados dinámicamente, como: el idioma sabe que 1 es entero, 2 es un número entero, pero no puede saber que la variable x siempre contiene un entero.


El entorno de tiempo de ejecución verifica estas etiquetas en diferentes momentos. Si intentamos doblar dos valores, puede verificar si son números, filas o matrices. Luego, ella doblará estos valores, los gluita o le dará un error, dependiendo del tipo.

Idiomas escortados estáticamente

Lenguajes estáticos Compruebe los tipos en el programa durante la compilación, antes de que se inicie el programa. Cualquier programa en el que los tipos violen las reglas del idioma se consideran incorrectas. Por ejemplo, la mayoría de los idiomas estáticos desestimarán la expresión "A" + 1 (Idioma C es una excepción a esta regla). El compilador sabe que "A" es una cadena, y 1 es un número entero, y ese + funciona solo cuando la parte izquierda y derecha pertenece a un tipo. Así que no necesita ejecutar el programa para comprender que hay un problema. Cada expresión en un lenguaje de mecanografía estática se refiere a un tipo específico que se puede determinar sin iniciar el código.


Muchos idiomas escortados estáticamente requieren un tipo. La función en Java Public Int agregará (int x, int y) toma dos enteros y devuelve el tercer entero. Otros idiomas estáticamente escritos pueden determinar el tipo automáticamente. La misma función de la adición en Haskell se ve así: agregue x y \u003d x + y. No informamos los tipos de tipos, pero puede definirlos usted mismo, porque sabe que + funciona solo en números, por lo que X e Y deben ser números, entonces la función AD toma dos números como argumentos.


Esto no reduce la "estatuto" de los tipos de tipos. El sistema de tipo en Haskell es famoso por su estática, severidad y poder, y en todos estos frentes Haskell está por delante de Java.

Idiomas tipificados dinámicamente

Los idiomas tipificados dinámicamente no requieren especificar tipo, pero tampoco lo determinan. Los tipos de variables son desconocidas hasta el momento en que tienen valores específicos al comenzar. Por ejemplo, una función en Python.


Def (x, y): devuelva x + y

puede plegar dos enteros, cadenas de pegamento, listas, etc., y no podemos entender qué sucede exactamente hasta que iniciamos el programa. Tal vez en algún momento la función F será causada por dos líneas, y con dos números en otro momento. En este caso, X e Y contendrán valores de diferentes tipos en diferentes momentos. Por lo tanto, se dice que los valores en idiomas dinámicos tienen un tipo, pero las variables y funciones, no. El valor de 1 es definitivamente un número entero, pero x e y puede ser cualquier cosa.

Comparación

La mayoría de los idiomas dinámicos emitirán un error si los tipos se utilizan incorrectamente (JavaScript es una cierta excepción; intenta devolver el valor de cualquier expresión, incluso cuando no tiene sentido). Al usar lenguajes tipificados dinámicamente, incluso un simple error del tipo "A" + 1 puede ocurrir en un entorno de combate. Los idiomas estáticos previenen dichos errores, pero, por supuesto, el grado de prevención depende de la potencia del sistema tipo.


Los idiomas estáticos y dinámicos se basan en ideas fundamentalmente diferentes sobre la exactitud de los programas. En el lenguaje dinámico "A" + 1, este es el programa correcto: se iniciará el código y aparecerá un error en el entorno de ejecución. Sin embargo, en la mayoría de los idiomas escritos estáticamente, la expresión "A" + 1 es no programa: No será compilado y no será lanzado. Este es un código incorrecto, así como un conjunto de caracteres aleatorios! &% ^ @ * &% ^ @ * - Este es un código incorrecto. Este es un concepto adicional de corrección y la incorrecta no tiene un equivalente en idiomas dinámicos.

Tipificación fuerte y débil.

Los conceptos de "fuerte" y "débil" son muy ambiguos. Aquí hay algunos ejemplos de su uso:

    A veces "fuerte" significa "estático".
    Es simple aquí, pero es mejor usar el término "estático", porque la mayoría usa y entiendelo.

    A veces significa "fuerte" significa "no hace una conversión de tipo implícito".
    Por ejemplo, JavaScript le permite escribir "A" + 1, que se puede llamar "tipificación débil". Pero casi todos los idiomas proporcionan uno u otro nivel de conversión implícita, lo que le permite proceder automáticamente a los números enteros a los números de punto flotante como 1 + 1.1. En realidad, la mayoría de las personas usan la palabra "fuerte" para determinar el límite entre una transformación aceptable e inaceptable. No hay una frontera generalmente aceptada, todos son inexactos y dependen de la opinión de una persona en particular.

    A veces, "fuerte" significa que es imposible eludir reglas estrictas para escribir en el idioma.

  • A veces, "fuerte" significa seguro para la memoria (seguro de memoria).
    C es un ejemplo de la memoria insegura para la memoria del lenguaje. Si XS es \u200b\u200buna matriz de cuatro números, entonces SI estará encantado de ejecutar el código XS o XS, devolviendo algún valor de la memoria inmediatamente para XS.

Vamos a parar. Así es como algunos idiomas cumplen con estas definiciones. Como puede ver, solo Haskell es "fuerte" en todos los parámetros. La mayoría de los idiomas no son tan claros.



("Cuando" en la columna "En la" conversión implícita "significa que la separación entre lo más fuerte y débil depende de las transformaciones que consideramos aceptables).


A menudo, los términos "fuertes" y "débiles" se refieren a una combinación indefinida de diferentes definiciones anteriores, y otras definiciones no se muestran aquí. Todo este trastorno hace que las palabras "fuertes" y "débiles" prácticamente no tienen sentido. Cuando quiera usar estos términos, es mejor describir qué significado exactamente. Por ejemplo, podemos decir que "Javascript devuelve un valor cuando la cadena se pliega con el número, pero Python devuelve un error". En este caso, no pasaremos nuestra fuerza en los intentos de llegar a un acuerdo sobre los muchos valores de la palabra "fuerte". O, incluso peor: vendremos a un malentendido no resuelto debido a la terminología.


En la mayoría de los casos, los términos "fuertes" y "débiles" en Internet son opiniones poco claras y mal definidas de personas específicas. Se utilizan para llamar al idioma "malo" o "bueno", y este dictamen se convierte en una jerga técnica.



Fuerte tipificación: el sistema de tipo que amo y con el que me siento cómodo.

Typificación débil: tipo de tipo que me molesta o con el que no me siento cómodo.

Escribiendo gradual (escribiendo gradual)

¿Puedo agregar tipos estáticos a idiomas dinámicos? En algunos casos, sí. En otros es difícil o imposible. El problema más obvio es Eval y otras posibilidades similares de los idiomas dinámicos. Realizar 1 + eval ("2") en Python da 3. Pero, ¿qué dará 1 + eval (Read_from_The_Network ())? Depende del hecho de que en la red en el momento de la ejecución. Si obtiene un número, la expresión es correcta. Si la cadena no está. Es imposible aprender antes de comenzar, por lo que es imposible analizar el tipo estáticamente.


La solución insatisfactoria en la práctica es especificar un tipo de evaluación () que recuerda a un objeto en algunos lenguajes o interfaz de programación orientados a objetos () en Go: este tipo a lo que cualquier valor satisface.


Cualquier valor no se limita a nada, por lo que desaparece la posibilidad de un sistema de tipo para ayudarnos en el Código de Eval. Los idiomas en los que existen ambos sistemas de evaluación y tipo deben rechazar la seguridad del tipo con cada uso de Eval.


En algunos idiomas, hay una escritura opcional o gradual (escritura gradual): son dinámicas de forma predeterminada, pero le permiten agregar algunas anotaciones estáticas. Python añadió recientemente tipos opcionales; TypeScript es un complemento sobre JavaScript, que tiene tipos opcionales; El flujo produce un análisis estático del antiguo código bueno en JavaScript.


Estos idiomas proporcionan algunas de las ventajas de la escritura estática, pero nunca darán garantías absolutas, como lenguas verdaderamente estáticas. Algunas funciones se escribirán estáticamente, y algunas se escribirán dinámicamente. El programador siempre necesita saber y temer la diferencia.

Compilación del código estáticamente escrito.

Cuando se compila una compilación de un código de escritura estáticamente, la sintaxis se verifica primero como en cualquier compilador. Entonces los tipos están marcados. Esto significa que el idioma estático primero puede quejarse a un error sintáctico, y después de que se fije, quejarse a 100 errores de tipificación. La corrección del error de sintaxis no creó estos 100 errores de mecanografía. El compilador simplemente no tenía la capacidad de detectar errores de tipo hasta que se corrija la sintaxis.


Los compiladores de idiomas estáticos generalmente pueden generar un código más rápido que los compiladores dinámicos. Por ejemplo, si el compilador sabe que la función Agregar toma enteros, puede usar la instrucción nativa del procesador de agregar central. ¿El lenguaje dinámico verificará el tipo al ejecutar, elegir una de las pluralidades de las funciones adicionales, dependiendo de los tipos (pliegue enteros o flotadores o pegue las cadenas o, quizás listas?) O debe decidir qué se produjo un error y los tipos no ocurrieron. corresponden entre sí. Todos estos cheques ocupan el tiempo. En idiomas dinámicos, se utilizan diferentes trucos para optimizar, como la compilación de JIT (justo a tiempo), donde el código se recompilará al realizar después de recibir toda la información necesaria sobre los tipos de información. Sin embargo, ningún lenguaje dinámico se puede comparar a velocidades con un código estático de forma gencial en el idioma como el óxido.

Argumentos a favor de los tipos estáticos y dinámicos.

Los partidarios del sistema tipo estático indican que sin tipo de tipo, los errores simples pueden llevar a problemas en la producción. Esto, por supuesto, es cierto. Cualquiera que usó un lenguaje dinámico lo experimentara.


Los partidarios de las lenguas dinámicas indican que en tales idiomas, parece que es más fácil escribir código. Esto es definitivamente justo para algunos tipos de código, que escribimos de vez en cuando, como, por ejemplo, el código con Eval. Esta es una solución controvertida para el trabajo regular, y aquí tiene sentido recordar la palabra incierta "fácilmente". Rich Hicks habló perfectamente sobre la palabra "fácilmente", y su conexión con la palabra "simplemente". Después de ver este informe, entenderá que no es fácil usar la palabra "Fácil". Joder "facilidad".


Los pros y los contras de los sistemas de tipificación estática y dinámica aún están mal estudiados, pero definitivamente dependen del idioma y la tarea específica que se resuelva.


JavaScript está tratando de continuar trabajando, incluso si significa una conversión sin sentido (como "A" + 1, dando "A1"). Python a su vez trata de ser conservadores y, a menudo, devuelve errores, como en el caso de "a" + 1.


Hay diferentes enfoques con diferentes niveles de seguridad, pero Python y Javascript son idiomas tipificados dinámicamente.



Haskell no permitirá la adición de enteros y flotar sin conversión explícita antes de eso. Si y Haskell están tipificados estáticamente, a pesar de las grandes diferencias.


Hay muchas variaciones de lenguas dinámicas y estáticas. Cualquier declaración incondicional del tipo "Los lenguajes estáticos es mejor que dinámica cuando se trata de x" es casi garantizado sin sentido. Puede ser cierto en el caso de idiomas específicos, pero es mejor decir que "Haskell es mejor que Python cuando se trata de X".

Una variedad de sistemas de escritura estática.

Echemos un vistazo a los dos ejemplos famosos de idiomas estáticamente escrupulados: Go y Haskell. En el sistema TIP, Go no tiene tipos generalizados, tipos con "parámetros" de otros tipos. Por ejemplo, puede crear su propio tipo para las listas de MyList, que pueden almacenar los datos que necesitemos. Queremos poder crear enteros de Mylist, Mylist Strings, etc., sin cambiar el código fuente de Mylist. El compilador debe seguir la tecla: si hay enteros de Mylist, y accidentalmente agregaremos una cadena allí, el compilador debe rechazar el programa.


Ir fue diseñado específicamente de tal manera que era imposible establecer los tipos como Mylist. Lo mejor que es posible hacer es crear una Mylist "Empale las interfaces": Mylist puede contener objetos, pero el compilador simplemente no conoce su tipo. Cuando obtenemos objetos de Mylist, necesitamos decirle al compilador de su tipo. Si decimos "Voy a obtener la cadena", pero en realidad, el valor es un número, entonces habrá un error de ejecución, como en el caso de los idiomas dinámicos.


También hay muchas otras características que están presentes en las lenguas modernas estáticamente (o incluso en algunas de las décadas de 1970). Los creadores de la marcha tenían sus propias razones para estas soluciones, pero la opinión de las personas por parte de esta ocasión a veces puede parecer bruscamente.


Ahora vamos a compararnos con Haskell, que tiene un sistema de tipo muy poderoso. Si especifica el tipo de MyList, el tipo de "Lista de números" es solo un entero de MyList. Haskell no nos dará la oportunidad de agregar una cadena a la lista y asegurarnos de que no pondremos un elemento de la lista en la variable de cadena.


Haskell puede expresar ideas mucho más complejas directamente por los tipos. Por ejemplo, NUM A \u003d\u003e Mylist A significa "Valores de MyList que se relacionan con un tipo de números". Esta puede ser una lista de "OB, flotar" de enteros o números decimales con precisión fija, pero definitivamente nunca será una lista de filas, que se verifica al compilar.


Puede escribir la función Agregar que funcione con cualquier tipo numérico. Esta función será el tipo NUM A \u003d\u003e (A -\u003e A -\u003e A). Significa:

  • a puede ser cualquier tipo numérico (NUM A \u003d\u003e).
  • La función toma dos argumentos de tipo A y devoluciones tipo A (A -\u003e A -\u003e A).

El último ejemplo. Si el tipo de función es una cadena -\u003e cadena, toma la cadena y devuelve la cadena. Pero si es una cadena -\u003e Cadena IO, también hace algún tipo de entrada / salida. Puede estar accediendo al disco a la red, leyendo desde el terminal y así sucesivamente.


Si la función está en el tipo. no IO, sabemos que no realiza ninguna operación de E / S. En la aplicación web, por ejemplo, puede entender si la función de la base de datos cambia simplemente mirando su tipo. No hay dinámicas y casi no hay lenguajes estáticos en tales. Esta es una característica de los idiomas con el sistema de escritura más potente.


En la mayoría de los idiomas, tendríamos que lidiar con la función y todas las funciones que se llaman desde allí, etc., al tratar de encontrar algo cambiando la base de datos. Este es un proceso tedioso en el que es fácil permitir un error. Y el sistema de tipo Haskell puede responder a esta pregunta simplemente y garantizada.


Compare este poder con Go, que no es capaz de expresar una idea simple de Mylist, sin mencionar la "función que toma dos argumentos, y son tanto numéricos como un tipo, y lo que hace que la entrada / salida".


El enfoque de IVE simplifica las herramientas de escritura para la programación en Go (en particular, la implementación del compilador puede ser simple). Además, se requiere aprender menos conceptos. Cómo estas ventajas son comparables con restricciones significativas: un problema subjetivo. Sin embargo, es imposible argumentar que Haskell es más difícil de explorar que ir, y que el tipo de tipo en Haskell es mucho más potente, y que Haskell puede evitar muchos más tipos de errores al compilar.


Go y Haskell son idiomas tan diferentes que su agrupación en una clase de "lenguajes estáticos" puede ser engañosa, a pesar del hecho de que el término se usa correctamente. Si comparas las ventajas prácticas de la seguridad, vaya más cerca de los idiomas dinámicos que a Haskell "Y.


Por otro lado, algunos idiomas dinámicos son más seguros que algunos idiomas estáticos. (Python en su conjunto se considera mucho más seguro que c). Cuando quiero hacer una generalización de idiomas estáticos o dinámicos como grupos, entonces no se olvide de la gran cantidad de diferencias entre los idiomas.

Ejemplos específicos de diferencias en las posibilidades de mecanografía de sistemas.

En sistemas de escritura más potentes, puede especificar restricciones en niveles más pequeños. Aquí hay algunos ejemplos, pero no lo detengan en ellos si la sintaxis es incomprensible.


En Go, puede decir "La función Agregar toma dos enteros" y devuelve entero ":


FUNC Agregar (x int, y int) int (retorno x + y)

En Haskell, puedes decir "Tarifa de características alguna Tipo numérico y devuelve el número del mismo tipo ":


F :: NUM A \u003d\u003e A -\u003e A -\u003e AÑADIR X Y \u003d X + Y

En Idris, puede decir que "la función toma dos enteros" y devuelve entero, pero el primer argumento debe ser menor que el segundo argumento ":


Agregar: (X: NAT) -\u003e (Y: NAT) -\u003e (Auto más pequeño: LT X Y) -\u003e NAT ADD X Y \u003d X + Y

Si intenta llamar a la función Agregar 2 1, donde el primer argumento es mayor que el segundo, entonces el compilador desestimará el programa durante la compilación. Es imposible escribir un programa donde el primer argumento es mayor que el segundo. Un lenguaje raro tiene tal oportunidad. En la mayoría de los idiomas, esta prueba se produce cuando se realiza: escribiríamos algo como si x\u003e \u003d y: elevar a alguna ().


En Haskell, no hay equivalente a un tipo de este tipo que en el ejemplo con los Idris anteriores, y en el principio no hay equivalente a experimentar con Haskell, o un ejemplo con IDRIS. Como resultado, IDRIS puede evitar muchos errores que no podrán prevenir la Haskell, y Haskell podrá evitar que muchos errores no se nadan. En ambos casos, se necesitan características adicionales del sistema de escritura, lo que hará que el idioma sea más complicado.

Sistemas de escribir algunos idiomas estáticos.

Aquí hay una lista aproximada de los sistemas de escribir algunos idiomas en el aumento de la potencia. Esta lista le dará una idea general del poder de los sistemas, usted no necesita tratarlo como una verdad absoluta. Los idiomas recopilados en un grupo pueden diferir mucho entre sí. Cada sistema de tipificación tiene sus propios problemas, y la mayoría de ellos son muy complejos.

  • C (1972), Go (2009): Estos sistemas no son de todo poderosos, sin el soporte de los tipos generalizados. Es imposible establecer el tipo de Mylist, que significaría la "Lista de enteros", "Lista de cadenas", etc. En su lugar, tendrá que hacer una "lista de valores inequívocos". Un programador debe informar manualmente "esta lista de la lista" cada vez que se extrae la cadena de la lista, y esto puede resultar en un error cuando la ejecución.
  • Java (1995), C # (2000): Ambos idiomas son compatibles con tipos generalizados, por lo que puede decir Mylist Y obtenga una lista de líneas, sobre las cuales el compilador sabe y puede monitorear la observancia de los tipos de tipos. Los elementos de la lista tendrán el tipo de cadena, el compilador forzará las reglas al compilar como de costumbre, de modo que los errores tengan menos probabilidades.
  • Haskell (1990), Rust (2010), SWIFT (2014): Todos estos idiomas tienen varias funciones avanzadas, incluidos tipos generalizados, tipos de datos algebraicos (ADTS) y tipos de tipos o algo similar (tipos de clases, características (rasgos) y protocolos, respectivamente). Rust y Swift son más populares que Haskell, y se promueven grandes organizaciones (Mozilla y Apple, respectivamente).
  • AGDA (2007), Idris (2011): Estos idiomas soportan los tipos dependientes, lo que le permite crear tipos como "una función que toma dos enteros x e y, donde y es mayor que x". Incluso el límite "Y es mayor que X" se ve obligado al compilar. Al realizar y, nunca será menor o igual que X, lo que suceda. Las propiedades muy sutiles, pero importantes del sistema se pueden verificar estáticamente en estos idiomas. Están estudiando muy pocos programadores, pero estos idiomas causan su enorme entusiasmo.

Existe un claro movimiento hacia sistemas de tipificación más potentes, especialmente si juzga la popularidad de los idiomas, y no por el simple hecho de la existencia de idiomas. Una excepción bien conocida es así, lo que explica por qué muchos partidarios de idiomas estáticos lo consideran un paso atrás.


El grupo dos (Java y C #) son idiomas principales, maduros y ampliamente utilizados.


El grupo tres está a punto de la entrada a la corriente principal, con un gran apoyo de Mozilla (Rust) y Apple (SWIFT).


El grupo cuatro (IDRIS y AGDA) están lejos de la corriente principal, pero puede cambiar con el tiempo. Los idiomas del grupo tres estaban lejos de la corriente principal hace diez años.

Tipificación estricta - Una de las opciones para trabajar con tipos de datos, que se utiliza en lenguajes de programación.

La escritura estricta implica las siguientes condiciones obligatorias:

  1. Cualquier objeto de datos (variable, constante, expresión) en el idioma siempre tiene un tipo estrictamente definido que se fija en el momento de la compilación del programa (escritura estática) o se determina durante la ejecución (escritura dinámica).
  2. Se permite asignar una variable solo un valor que tiene un mismo tipo estrictamente el mismo tipo de datos que la variable, se aplican las mismas limitaciones para transmitir parámetros y devolver los resultados de las funciones.
  3. Cada operación requiere los parámetros de tipos estrictamente definidos.
  4. No se permite la conversión de tipo implícito (es decir, el traductor percibe ningún intento de usar el valor del tipo incorrecto que se describió para una variable, parámetro, funciones u operaciones, como un error de sintaxis).

Con el seguimiento con precisión, los requisitos de la escritura estricta, incluso las mismas cantidades de valores y los tipos de datos permitidos son incompatibles. Si el programa necesita asignar un valor de un tipo de variable de otro tipo, esto se puede hacer, pero solo al aplicar explícitamente una operación de transformación de tipo especial, que en tales casos suele ser parte del lenguaje de programación (aunque puede que no sea formalmente, y proporcionado por bibliotecas estándar).

El único lenguaje de programación prácticamente utilizado con escritura estricta es el infierno. Un número bastante grande de lenguajes de programación comunes usan la escritura estática no estática. Tales idiomas incluyen, por ejemplo, Pascal, Module-2, Java. Seguramente describen los tipos de variables, parámetros y funciones, pero se permiten los tipos implícitos de tipos, si el valor de un tipo se asigna a la variable del otro, el compilador genera automáticamente el código para convertir el valor al valor deseado. Escriba si solo una conversión de este tipo conduce a la pérdida de datos. Por ejemplo, un número entero puede asignarse mediante una variable declarada como un número de punto flotante, y la asignación inversa sin una aclaración de tipo explícito está prohibida, ya que con una alta probabilidad resultará en un error. Algunos idiomas que tienen formalmente el concepto de tipo de datos, en realidad se pueden considerar inepitis. Estos idiomas incluyen Classic C, en el que, aunque se requiere la Declaración de Tipos, en realidad, todos los tipos de datos son la asignación compatible (las compilaciones modernas de C limitan esta libertad y emite al menos advertencias con tipos peligrosos).

En la teoría de la programación, la escritura estricta es un elemento indispensable para garantizar la confiabilidad del software desarrollado. Con el uso adecuado (implicaba que el programa se anuncie y separe los tipos de datos para valores lógicamente incompatibles), protege al programador de errores simples, pero difíciles asociados con el intercambio de valores lógicamente incompatibles que se producen a veces simplemente debido al reloj elemental. Dichos errores se revelan en la etapa de compilación del programa, mientras que con la capacidad de traer implícitamente casi cualquier tipo entre sí (como, por ejemplo, en el SI clásico), estos errores se detectan solo cuando se prueban, y no todo no es de inmediato. Por otro lado, a muchos programadores profesionales no les gusta la tipificación estricta debido a su inconveniente, aumenta el volumen del programa y el momento de la escritura, requiere un estudio más completo del código, lo que parece innecesario.

Este artículo contiene el mínimo necesario de aquellas cosas que solo necesita saber sobre la escritura, para no llamar la escritura dinámica por el mal, el LISP es un idioma tetonoso y el lenguaje C con estricto tipificación.

En la versión completa hay una descripción detallada de todos los tipos de escritura, sazonados con ejemplos de código, referencias a lenguajes de programación populares y imágenes explícitas.

Recomiendo leer primero una breve versión del artículo y luego con deseo y completo.

Versión breve

Las lenguas de programación de la tipificación son habituales para dividir en dos campamentos grandes. tipos y netipelays (básico). A la primera, por ejemplo, C, Python, Scala, PHP y LUA incluyen, y el segundo es el lenguaje del ensamblador, hacia atrás y el cerebro.

Dado que "la tipificación convencional" es intrínsecamente simple como un atasco de tráfico, entonces no se divide en ninguna otra especie. Pero las lenguas escritas se dividen en varias otras categorías de intersección:

  • Estático / dinámica Tipificación. Estática está determinada por el hecho de que los tipos finales de variables y funciones se establecen en la etapa de compilación. Esos. Ya el compilador está 100% seguro de qué tipo se encuentra donde se encuentra. En la escritura dinámica, ya se encuentran todos los tipos durante la ejecución del programa.

    Ejemplos:
    Estático: C, Java, C #;
    Dinámico: Python, JavaScript, Ruby.

  • Fuerte / débil La tipificación (también a veces dice estricto / no golpeado). El hecho de que la escritura fuerte se asigna por el hecho de que el idioma no le permite mezclar diferentes tipos en expresiones y no implica automáticamente las conversiones, por ejemplo, no puede deducir desde el conjunto de cadenas. Los idiomas con tipificación débil realizan una variedad de transformaciones implícitas automáticamente, incluso si la pérdida de precisión o la conversión pueden ocurrir en ambigüedad.

    Ejemplos:
    Fuerte: Java, Python, Haskell, Lisp;
    Débil: C, JavaScript, Visual Basic, PHP.

  • Explícito / noavid Tipificación. Los idiomas escritos explícitos se distinguen por el hecho de que el tipo de nuevas variables / funciones / sus argumentos debe especificarse explícitamente. En consecuencia, las lenguas con la tipificación implícita cambian esta tarea en el compilador / intérprete.

    Ejemplos:
    Explícito: C ++, D, C #
    Implícito: PHP, LUA, JavaScript

También se debe tener en cuenta que todas estas categorías intersectan, por ejemplo, el idioma C tiene una tipificación explícita estática y estática, y el lenguaje de Python es una fuerte implícita dinámica.

Sin embargo, no menos que los idiomas de las tipias estáticas y dinámicas al mismo tiempo. A pesar de correr adelante, diré que estoy aquí, realmente existen, pero al respecto más tarde.

Versión detallada

Si una breve versión no parecía suficiente, buena. ¿No es de extrañar que escribiera un detallado? Lo principal es que en una breve versión fue simplemente imposible de adaptarse a toda la información útil e interesante, y los detalles serían demasiado largos que todos pudieran leerlo, no se esforzan.

Tipificación básica

En los lenguajes de programación de pechos, todas las entidades se consideran simplemente secuencias de bits, diferentes longitudes.

La tipificación Bestipa es generalmente inherente a los idiomas de bajo nivel (ensamblador,) y esotérico (Brainfuck, HQ9, PIET). Sin embargo, ella, junto con las desventajas, tienen algunas ventajas.

Beneficios
  • Le permite escribir en un nivel máximo bajo, y el compilador / intérprete no interferirá con ningún tipo de tipos. Usted es libre de producir cualquier operación en cualquier tipo de datos.
  • El código resultante suele ser más eficiente.
  • Transparencia de las instrucciones. Con el conocimiento del idioma, generalmente no hay duda de que uno u otro código representa.
desventajas
  • Complejidad. A menudo, existe la necesidad de presentar valores integrales, como listas, filas o estructuras. Puede haber inconvenientes.
  • No hay cheques. Cualquier acción sin sentido, como la resta de un puntero a una matriz del símbolo, se considerará completamente normal, lo que está lleno de errores de empleo.
  • Baja abstracción. Trabajar con cualquier tipo de datos complejo no es diferente de trabajar con números, que, por supuesto, creará muchas dificultades.
¿Fuerte tipificación espinosa?
Sí, existe. Por ejemplo, en el idioma del ensamblador (para la arquitectura X86 / X86-64, no conozco a los demás), no puede ensamblar el programa si intenta cargar en los datos del Registro CX (16 bits) desde el registro RAX (64 bits ).

MOV CX, EAX; Tiempo de montaje de error

¿Así que resulta que todavía está escribiendo en el assemor? Creo que estos controles no son suficientes. Y tu opinión, por supuesto, depende solo de ti.

Tyming estático y dinámico.

Lo principal es que distingue a la escritura estática (estática) de la dinámica (dinámica) que todos los tipos de tipos se realizan en la etapa de compilación, no la etapa de ejecución.

Algunas personas pueden parecer que la escritura estática es demasiado limitada (de hecho, es, pero durante mucho tiempo ha estado deshaciéndose de algunos métodos). De la misma manera que los idiomas tipificados dinámicamente son un juego con fuego, pero ¿qué características están asignadas? ¿Ambas especies tienen la probabilidad de existencia? Si no, ¿por qué hay muchos más que idiomas estáticamente y tipificados dinámicamente?

Vamos a resolverlo.

Beneficios de la escritura estática.
  • Los cheques de tipo ocurren solo una vez, en la etapa de compilación. Y esto significa que no tendremos que descubrir constantemente si estamos tratando de dividir el número en la cadena (y dar el error o transformar).
  • Velocidad de rendimiento. Se desprende del punto anterior que los idiomas que mecanografiados estáticamente son casi siempre más rápidos que las tipificadas dinámicamente.
  • Con algunas condiciones adicionales, le permite detectar potenciales errores en la etapa de compilación.
  • Aceleración del desarrollo con soporte IDE (opciones de tamizado, obviamente no adecuadas por tipo).
Ventajas de la escritura dinámica.
  • Fácil de crear colecciones universales: un grupo de todos y todos (rara vez surge esa necesidad, pero cuando la escritura dinámica surge para ayudar).
  • Facilidad de describir algoritmos generalizados (por ejemplo, clasificar una matriz que funcionará no solo en la lista de enteros, sino también en la lista de reales e incluso en la lista de líneas).
  • Fácil en desarrollo: los idiomas con tipilación dinámica suelen ser muy buenos para comenzar la programación.

Programación generalizada
Bueno, el argumento más importante para la escritura dinámica es la conveniencia de describir algoritmos generalizados. Imaginemos un problema: necesitamos una función de búsqueda para varias matrices (o listas), por la matriz de enteros, de acuerdo con la matriz de los personajes real y la matriz.

¿Cómo lo resolveremos? Lo resuelvo en los 3º lenguajes diferentes: uno con tipificación dinámica y dos con estática.

Buscar algoritmo Tomaré uno de los más simples. La función recibirá el elemento deseado, la matriz en sí (o la lista) y devolverá el índice del elemento, o si el elemento no se encuentra - (-1).

Solución dinámica (Python):
DEF Buscar (Requery_Element, LISTA): para (índice, elemento) en enumeración (lista): if element \u003d\u003d requerido_element: retorno del índice de retorno (-1)

Como puede ver, todo es simple y no hay problema con el hecho de que la lista pueda contener al menos números, aunque no haya otras matrices. Muy bien. Vamos a seguir - ¡Decide esta tarea en C!

Solución estática (C):
INTSIGNED IND Find_int (INT PEDIDE_ELEMENT, INT ARRAY, TAMAÑO DE INT sin firmar) (para (no firmado int i \u003d 0; i< size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_float(float required_element, float array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); } unsigned int find_char(char required_element, char array, unsigned int size) { for (unsigned int i = 0; i < size; ++i) if (required_element == array[i]) return i; return (-1); }

Bueno, cada función es individualmente similar a la versión de Python, pero ¿por qué hay tres? ¿Es realmente la programación estática?

Si y no. Hay varias técnicas de programación, una de las cuales ahora consideramos. Se llama programación generalizada y el lenguaje C ++ lo apoya bien. Veamos la nueva versión:

Solución estática (programación generalizada, C ++):
Plantilla. INT no firmado Encuentre (T Requiry_Element, Std :: Vector matriz) (por insignificada int i \u003d 0; i< array.size(); ++i) if (required_element == array[i]) return i; return (-1); }

¡Okey! No parece mucho más difícil que la versión en Python y, al mismo tiempo, no tuvo que escribir mucho. Además, obtuvimos la implementación para todas las matrices, ¡y no solo por la tercera vez necesaria para resolver el problema!

Esta versión parece ser exactamente lo que necesita: obtenemos al mismo tiempo las ventajas de la escritura estática y algunas ventajas son dinámicas.

Es genial que generalmente sea posible, pero tal vez incluso mejor. Primero, la programación generalizada puede ser más conveniente y más hermosa (por ejemplo, en Haskell). En segundo lugar, además de la programación generalizada, también es posible aplicar un polimorfismo (el resultado será peor), la sobrecarga de funciones (de manera similar) o macros.

Estadísticas en Dinámica
También es necesario mencionar que muchos idiomas estáticos le permiten usar la escritura dinámica, por ejemplo:
  • C # admite dinámica de tipo pseudo.
  • F # ¡Admite el azúcar de sintaxis en forma de operador?, Sobre la base de la cual se puede implementar la imitación de la escritura dinámica.
  • Haskell: la escritura dinámica es proporcionada por el módulo Data.Dynamic.
  • Delphi - a través de un tipo especial de variante.
Además, algunos idiomas tipificados dinámicamente le permiten aprovechar la escritura estática:
  • Declaración de tipos de lisp común.
  • Perl - de la versión 5.6, bastante limitado.
¿Así que continúa?

Typisius fuerte y débil

Los idiomas con una escritura fuerte no permiten mezclar la esencia de diferentes tipos en expresiones y no realizar ninguna transformación automática. También llaman "idiomas con escritura estricta". Término inglés para esto - fuerte mecanografía.

Idiomas débiles tipificados, por el contrario, en plena grasa, de modo que el programador mezcle diferentes tipos en una expresión, y el propio compilador resultará en un solo tipo. También se llaman "idiomas con tipificación no inicial". El término en inglés para esto es una escritura débil.

La tipificación débil a menudo se confunde con dinámica, que es completamente incorrecta. Un lenguaje tipificado dinámicamente puede ser débil y fuertemente escrito.

Sin embargo, pocos que adjuntan el valor del rigor de la escritura. A menudo se afirma que si el idioma está escrito estáticamente, puede capturar muchos errores potenciales al compilar. ¡Te mienten!

El idioma debe tener más y fuerte mecanografía. Y la verdad, si el compilador en lugar de un mensaje de error simplemente agregará una fila al número, o lo que es aún peor, la deducción de una matriz es diferente, ¿cuál es el uso de que todos los "cheques" de los tipos serán En la etapa de compilación? ¡Eso es correcto: la escritura estática débil es aún peor que la fuerte dinámica! (Bueno, esta es mi opinión)

Entonces, ¿qué pasa con el débil TypiSius no tiene suficiente más? Tal vez se vea así, pero a pesar del hecho de que debería estar de acuerdo con un partidario exhaustivo de la escritura fuerte, también tiene ventajas.

¿Quieres saber qué?

Beneficios de la fuerte mecanografía.
  • Fiabilidad: obtendrá una excepción o error de compilación, en lugar de un comportamiento incorrecto.
  • Velocidad: en lugar de transformaciones ocultas que pueden ser bastante caras, con una escritura fuerte, es necesario escribirlas claramente, lo que hace que un programador al menos sepa que esta sección del código puede ser lenta.
  • Comprender el trabajo del programa: nuevamente, en lugar de los tipos impregnados de tipos, el programador lo escribe todo mismo, lo que significa que entiende aproximadamente que la comparación de la cadena y el número no sucede por sí mismo.
  • Nota: cuando escribe la conversión manualmente, sabe exactamente lo que se convierte y qué. También siempre entenderá que tales transformaciones pueden llevar a la pérdida de precisión y los resultados incorrectos.
Las ventajas de la escritura débil.
  • Facilidad de uso de expresiones mixtas (por ejemplo, de enteros y números reales).
  • Abstracción de escribir y enfocarse en la tarea.
  • Breve grabación.
¡Está bien, lo descubrimos, también resulta tener una tipificación débil, ¡hay ventajas! ¿Hay alguna forma de mover los pros de la tipificación débil en fuerte?

Resulta que incluso dos.

Aclaración implícita de los tipos, en situaciones inequívocas y sin pérdida de datos.
Wow ... un artículo bastante largo. Permítanme continuar reduciéndolo a la "transformación implícita limitada", entonces, ¿qué significa la situación inequívoca y la pérdida de datos?

Una situación inequívoca es una transformación o una operación en la que se entiende inmediatamente la esencia. Por ejemplo, la adición de dos números es una situación inequívoca. Y la transformación del número en una matriz no es (es posible crear una matriz de un elemento, posiblemente una matriz, con elementos predeterminados, y el número se puede convertir en la cadena y luego en la cadena. Una matriz de caracteres).

La pérdida de datos es aún más fácil. Si convierte un número real 3.5 a la totalidad, perderemos parte de los datos (de hecho, esta operación también es ambigua: ¿cómo se redondeará? ¡También? De una manera más pequeña? ¿Cae la parte fraccional?).

Las transformaciones en situaciones ambiguas y la conversión con pérdida de datos son muy, muy mal. No hay nada peor en la programación.

Si no me cree, aprenda el idioma PL / I o simplemente busque su especificación. ¡Tiene reglas para la transformación entre todo tipo de datos! ¡Es el infierno!

De acuerdo, recordemos la conversión implícita limitada. ¿Hay tales idiomas? Sí, por ejemplo, en Pascal, puede convertir un entero en uno real, pero no viceversa. También se encuentran mecanismos similares en C #, maravilloso y lisp común.

Bueno, dije que todavía hay una manera de obtener un par de ventajas de la tipificación débil en un lenguaje fuerte. Y sí, es y llamado el polimorfismo de los diseñadores.

Lo explicaré en el ejemplo de una lengua maravillosa Haskell.

Los diseñadores polimórficos aparecieron como resultado de la observación, que a menudo se necesitan transformaciones seguras implícitas cuando se utilizan literales numéricos.

Por ejemplo, en la expresión PI + 1, no quiero escribir PI + 1.0 o PI + FLOAT (1). ¡Quiero escribir solo Pi + 1!

Y esto se hace en Haskell, debido al hecho de que el literal 1 no tiene un tipo específico. Esto no es ni ni real ni complejo. ¡Es solo un número!

Como resultado, al escribir una función de suma simple XY, moviendo todos los números de x a y (con incremento en 1), obtenemos varias versiones: suma para enteros, suma de real, suma para racional, suma para números complejos e incluso suma Para todos estos tipos numéricos que ellos mismos han identificado.

Por supuesto, esta recepción se guarda solo cuando se usa expresiones mixtas con literales numéricos, y esto es solo la parte superior del iceberg.

Por lo tanto, se puede decir que la mejor salida se equilibrará por el borde, entre la escritura fuerte y débil. Pero si bien el equilibrio perfecto no tiene ningún idioma, por lo que estoy más inclinado a los idiomas tipificados fuertemente (como Haskell, Java, C #, Python), y no se escribió débilmente (como C, JavaScript, Lua, PHP).

Tipificación explícita e implícita.

El idioma con la tipificación explícita asume que el programador debe especificar los tipos de todas las variables y funciones que anuncian. Término de inglés para esto: escribiendo explícito.

El idioma con la tipificación implícita, por el contrario, le ofrece a olvidarse de los tipos y cambiar la tarea de emitir tipos al compilador o intérprete. Término de inglés para esto - tipificación implícita.

Al principio, es posible decidir que la escritura implícita es equivalente a la dinámica, y explícitamente estática, pero luego veremos que no lo es.

¿Hay alguna ventaja de cada especie, y nuevamente, hay alguna combinación y hay idiomas con el apoyo de ambos métodos?

Ventajas de la tipificación explícita.
  • La presencia de la función de firma (por ejemplo, INT ADD (INT, INT)) le permite determinar sin ningún problema que haga la función.
  • El programador escribe inmediatamente cómo se puede almacenar el tipo de valor en una variable específica, que elimina la necesidad de memorizarla.
Las ventajas de la escritura implícita.
  • RECUERDO REDUCCIÓN: DEF Agregar (X, Y) es claramente más corta que int x, int y).
  • Resistencia a los cambios. Por ejemplo, si la función de variable temporal fue del mismo tipo que el argumento de entrada, luego en un lenguaje escribido explícitamente cuando se cambia el tipo de argumento, también se cambiará el tipo de variable temporal.
Bueno, se puede ver que ambos enfoques tienen tanto los pros y los contras (¿y quién esperaba algo más?), ¡Así que vamos a encontrar maneras de combinar estos dos enfoques!
Tipificación explícita
Hay idiomas, con una tipificación implícita del valor predeterminado y la capacidad de especificar el tipo de valores si es necesario. Este tipo de traductor de expresión se mostrará automáticamente. Uno de estos idiomas es Haskell, déjame dar un ejemplo simple, para mayor claridad:
- Sin indicación explícita del tipo ADD (X, Y) \u003d X + Y - Indicación explícita del tipo ADD :: (entero, entero) -\u003e Entero Agregar (x, y) \u003d x + y

Nota: Tenía la intención de usar una función no marcada, y también tiene la intención de registrar una firma privada en lugar de agregar más general :: (NUM A) \u003d\u003e A -\u003e A -\u003e A *, porque Quería mostrar la idea, sin explicar la sintaxis de Haskell "a.

Para simplemente explicar las dos tecnologías absolutamente diferentes, comience primero. Lo primero que se enfrenta a un programador al escribir código - Declaración de variables. Puede notar que, por ejemplo, en el lenguaje de programación de C ++, debe especificar el tipo de variable. Es decir, si declara la variable x, entonces debe agregar un INT - para almacenar datos enteros, flotar es para almacenar datos de puntos flotantes, caracterización de datos simbólicos y otros tipos disponibles. En consecuencia, la escritura estática se usa en C ++, así como en su predecesor C.

¿Cómo funciona el trabajo de escritura estática?

En el momento del anuncio, el compilador variable debe saber qué funciones y parámetros pueden usar con respecto a él, y que no lo es. Por lo tanto, el programador necesita designar inmediatamente el tipo de variable. Tenga en cuenta que durante el código de ejecución, el tipo de variable no se puede cambiar. Pero puede crear su propio tipo de datos y usarlo a continuación.

Considera un pequeño ejemplo. Al inicializar la variable x (int x;), especificamos un identificador INT: esta es una reducción de la cual almacena solo enteros en el rango de - 2 147 483 648 a 2 147 483 647. Por lo tanto, el compilador entiende que los valores matemáticos entienden los valores matemáticos Puede realizar por encima de esta variable: cantidad, diferencia, multiplicación y división. Pero, por ejemplo, la función STRCAT (), que conecta dos valores del tipo de caracter, no se puede aplicar a X. Después de todo, si elimina las restricciones e intente conectar los dos valores del método int a un método simbólico, se producirá un error.

¿Por qué necesitó idiomas con tipificación dinámica?

A pesar de algunas restricciones, la escritura estática tiene una serie de ventajas, y no trae mucha incomodidad al escribir algoritmos. Sin embargo, se pueden necesitar más "reglas gratuitas" para diferentes propósitos en términos de tipos de datos.

Un buen ejemplo, que puede ser llevado - JavaScript. Este lenguaje de programación se usa generalmente para incrustarlo en un marco para obtener acceso funcional a los objetos. Debido a este particular, ganó gran popularidad en las tecnologías web, donde se siente perfectamente la escritura dinámica. Algunos simplifican la escritura de scripts pequeños y macros. Y también aparece una ventaja en las variables de reutilización. Pero esta oportunidad se usa bastante rara, debido a posibles errores confusos.

¿Qué tipo de tipificación es mejor?

Disputas que la escritura dinámica es mejor que estricta, no cese hasta este día. Por lo general, surgen de programadores altamente especializados. Por supuesto, los desarrolladores web utilizan todas las ventajas de la escritura dinámica para crear un código de alta calidad y un producto de software final. Al mismo tiempo, los programadores del sistema que desarrollan los algoritmos más complejos en lenguajes de programación de bajo nivel, generalmente no necesitan tales oportunidades, por lo que son suficientes escrituras estáticas. Por supuesto, hay excepciones de las reglas. Por ejemplo, una tipificación dinámica en Python está completamente implementada.

Por lo tanto, para determinar el liderazgo de esta o esa tecnología, solo es necesario a partir de los parámetros de entrada. La escritura dinámica es mejor adecuada para el desarrollo de marcos ligeros y flexibles, mientras que para crear una arquitectura masiva y compleja, es mejor usar una escritura estricta.

Separación en la escritura "fuerte" y "débil".

Entre los materiales de habla rusa y de habla inglesa en la programación se pueden encontrar la expresión: la escritura "fuerte". Este no es un concepto separado, o más bien, tal concepto en Léxico profesional no existe en absoluto. Aunque muchos están tratando de interpretarlo de manera diferente. De hecho, la tipificación "fuerte" debe entenderse como la que es conveniente para usted y con lo que es más cómodo trabajar tanto como sea posible. Y "débil" es un sistema incómodo e ineficaz para usted.

Característica del orador

Seguramente usted notó que, en la etapa de escribir el Código, el compilador analiza los diseños escritos y da un error cuando los tipos de datos son miserablemente. Pero solo no es JavaScript. Su singularidad es que funcionará en cualquier caso. Aquí hay un ejemplo fácil: queremos doblar el símbolo y el número que no tiene sentido: "X" + 1.

En los idiomas estáticos, dependiendo del idioma en sí, esta operación puede tener diferentes consecuencias. Pero en la mayoría de los casos, ni siquiera se permitirá antes de la recopilación, ya que el compilador le dará un error inmediatamente después de escribir un diseño de este tipo. Simplemente lo considera incorrecto y será completamente correcto.

En los idiomas dinámicos, esta operación se puede hacer, pero en la mayoría de los casos, un error seguirá la etapa de ejecución del código, ya que el compilador no analiza los tipos de datos en tiempo real y no puede decidir errores en esta área. JavaScript es único, ya que ejecutará tal operación y recibirá un conjunto de caracteres ilegibles. A diferencia de otros idiomas que simplemente completan el programa.

¿Las arquitecturas relacionadas son posibles?

En este momento, no existe una tecnología adyacente que podría mantener simultáneamente la escritura estática y dinámica en lenguajes de programación. Y puede decir con confianza que no aparecerá. Dado que las arquitecturas difieren entre sí en conceptos fundamentales y no se pueden usar simultáneamente.

Pero, sin embargo, en algunos idiomas puede cambiar la escritura utilizando marcos adicionales.

  • En el lenguaje de programación Delphi - subsistema de variante.
  • En el lenguaje de programación ALICEML - Paquetes adicionales.
  • En el lenguaje de programación Haskell - la biblioteca Data.Dynamic.

¿Cuándo es un estricto escribiendo realmente mejor que dinámico?

Aprobar de manera inequívoca la ventaja de la escritura estricta sobre dinámica solo si usted es un programador para principiantes. Esto converge absolutamente a todos los especialistas de TI. Al enseñar las habilidades de programación fundamentales y básicas, es mejor usar estricto tipificación para adquirir cierta disciplina cuando se trabaja con variables. Luego, si es necesario, puede cambiar a la dinámica, pero las habilidades de trabajo adquiridas con estricta tipificación desempeñarán su importante papel. Aprenderá a verificar cuidadosamente las variables y tener en cuenta sus tipos al diseñar y escribir el código.

Ventajas de la escritura dinámica.

  • Minimizando la cantidad de caracteres y filas del Código debido a la uniformidad para la declaración preliminar de las variables y las instrucciones de su tipo. El tipo se determinará automáticamente, después de asignar el valor.
  • En pequeños bloques del Código, la percepción visual y lógica de las estructuras se simplifica, debido a la falta de filas de declaración "innecesarias".
  • El altavoz tiene un efecto positivo en la velocidad del compilador, ya que no tiene en cuenta los tipos, y no los revisa para el cumplimiento.
  • Aumenta la flexibilidad y le permite crear diseños universales. Por ejemplo, al crear un método que debe interactuar con la matriz de datos, no necesita crear funciones separadas para trabajar con numéricos, texto y otros tipos de matrices. Suficiente para escribir un método, y funcionará con cualquier tipo.
  • Simplifica la salida de datos de los sistemas de administración de la base de datos, por lo que la escritura dinámica se usa activamente al desarrollar aplicaciones web.

Lea más sobre las lenguas de programación con la tipificación estática

  • C ++ es el lenguaje de programación de propósito general más común. Hasta la fecha, tiene varias ediciones importantes y un gran ejército de usuarios. Se hizo popular debido a su flexibilidad, expansión ilimitada y apoyo de diversos paradigmas de programación.

  • Java es un lenguaje de programación que utiliza un enfoque orientado a objetos. Recibido debido a la forma multiplata. Al compilar el código se interpreta en bytes, que se puede realizar en cualquier sistema operativo. Java y la escritura dinámica son incompatibles, ya que el idioma está estrictamente escrito.

  • Haskell también es uno de los idiomas populares cuyo código se puede integrar en otros idiomas e interactuar con ellos. Pero a pesar de esta flexibilidad, tiene estricto tipificación. Equipado con un gran conjunto incorporado de tipos y la posibilidad de crear su propia.

Lea más sobre las lenguas de programación con el tipo dinámico de mecanografía

  • Python - lenguaje de programación que se creó principalmente para facilitar el trabajo del programador. Tiene una serie de mejoras funcionales, que aumentan la legibilidad del código y lo escriben. Esto se logró en gran medida gracias a la escritura dinámica.

  • PHP - Idioma para crear scripts. En todas partes se aplica al desarrollo web, proporcionando interacción con las bases de datos, para crear páginas web dinámicas interactivas. Gracias a la escritura dinámica, trabajar con bases de datos se facilita significativamente.

  • JavaScript: el lenguaje de programación ya mencionado anteriormente, que ha encontrado la aplicación en tecnologías web para crear escenarios web que se ejecutan en el lado del cliente. La escritura dinámica se utiliza para facilitar la escritura de código, ya que generalmente se divide en pequeños bloques.

Tipo dinámico de mecanografía - Desventajas

  • Si se realizó un error tipográfico o un error aproximado al usar o declarar variables, el compilador no lo muestra. Y surgirán problemas al ejecutar el programa.
  • Al usar la escritura estática, todas las declaraciones de variables y funciones generalmente se eliminan en un archivo separado que le permite crear fácilmente la documentación o usar el archivo en sí mismo como la documentación. En consecuencia, la escritura dinámica no permite usar tal característica.

Resumir

La escritura estática y dinámica se utilizan para fines completamente diferentes. En algunos casos, los desarrolladores persiguen las ventajas funcionales y en algunos motivos puramente personales. En cualquier caso, para determinar el tipo de escritura para usted, es necesario examinarlos cuidadosamente en la práctica. En el futuro, al crear un nuevo proyecto y la opción de escribir para él, esto desempeñará un papel importante y dará una comprensión de una opción efectiva.



¿Te gustó el artículo? Compártelo