una solo puede propiedad lectura indizador encontrado coincidencia asignar ambiguousmatchexception ambigua c# java python perl weakly-typed

c# - solo - Buscando aclaraciones sobre aparentes contradicciones con respecto a los idiomas débilmente tipados



no se puede asignar la propiedad o el indizador es de solo lectura (9)

ACTUALIZACIÓN: Esta pregunta fue el tema de mi blog el 15 de octubre de 2012. ¡ Gracias por la gran pregunta!

¿Qué significa realmente que un idioma sea "débilmente tipado"?

Significa que "este lenguaje usa un sistema de tipo que me parece desagradable". Un lenguaje "fuertemente tipado" en contraste es un lenguaje con un sistema de tipos que me parece agradable.

Los términos son esencialmente insignificantes y debes evitarlos. Wikipedia enumera once significados diferentes para "fuertemente tipificado", varios de los cuales son contradictorios. Esto indica que las probabilidades de confusión que se crean son altas en cualquier conversación que involucre el término "fuertemente tipado" o "débilmente tipado".

Todo lo que se puede decir con certeza es que un lenguaje "fuertemente tipado" en discusión tiene alguna restricción adicional en el sistema de tipos, ya sea en tiempo de ejecución o en tiempo de compilación, que carece de un lenguaje "débilmente tipado". Lo que esa restricción podría ser no puede determinarse sin contexto adicional.

En lugar de utilizar "fuertemente tipado" y "débilmente tipado", debe describir en detalle a qué tipo de seguridad de tipo te refieres. Por ejemplo, C # es un lenguaje estáticamente tipado y un lenguaje seguro y un lenguaje seguro para la memoria , en su mayor parte . C # permite que se violen las tres formas de tipeo "fuerte". El operador de elenco viola el tipado estático; le dice al compilador "Sé más sobre el tipo de tiempo de ejecución de esta expresión que tú". Si el desarrollador está equivocado, el tiempo de ejecución lanzará una excepción para proteger la seguridad del tipo. Si el desarrollador desea romper la seguridad de tipo o la seguridad de la memoria, puede hacerlo desactivando el sistema de seguridad tipo haciendo un bloqueo "inseguro". En un bloque inseguro puede usar la magia del puntero para tratar un int como un float (violando la seguridad del tipo) o para escribir en la memoria que no le pertenece. (Violando la seguridad de la memoria)

C # impone restricciones de tipo que se comprueban tanto en tiempo de compilación como en tiempo de ejecución, lo que lo convierte en un lenguaje "fuertemente tipado" en comparación con los lenguajes que realizan menos comprobaciones en tiempo de compilación o menos revisiones en tiempo de ejecución. C # también le permite, en circunstancias especiales, realizar un análisis final de esas restricciones, lo que lo convierte en un lenguaje "débilmente tipado" en comparación con los idiomas que no le permiten realizar dicha ejecución final.

¿Qué es realmente? Es imposible decirlo; depende del punto de vista del hablante y su actitud hacia las diversas características del lenguaje.

Creo que entiendo el tipeo fuerte , pero cada vez que busco ejemplos para lo que es mecanografía débil, termino encontrando ejemplos de lenguajes de programación que simplemente fuerzan / convierten tipos automáticamente.

Por ejemplo, en este artículo llamado Typing: Strong vs. Weak, Static vs. Dynamic dice que Python está fuertemente tipado porque se obtiene una excepción si se intenta:

Pitón

1 + "1" Traceback (most recent call last): File "", line 1, in ? TypeError: unsupported operand type(s) for +: ''int'' and ''str''

Sin embargo, tal cosa es posible en Java y en C #, y no los consideramos tipeados débilmente solo por eso.

Java

int a = 10; String b = "b"; String result = a + b; System.out.println(result);

DO#

int a = 10; string b = "b"; string c = a + b; Console.WriteLine(c);

En este otro artículo llamado Weakly Type Languages, el autor dice que Perl está débilmente tipado simplemente porque puedo concatenar una cadena a un número y viceversa sin ninguna conversión explícita.

Perl

$a=10; $b="a"; $c=$a.$b; print $c; #10a

Entonces, el mismo ejemplo hace que Perl escriba débilmente, pero no Java y C #.

Gee, esto es confuso

Los autores parecen dar a entender que un lenguaje que impide la aplicación de ciertas operaciones en valores de diferentes tipos está fuertemente tipado y lo contrario significa débilmente tipado.

Por lo tanto, en algún momento me he sentido motivado a creer que si un lenguaje proporciona muchas conversiones automáticas o coerción entre tipos (como perl) puede terminar considerándose débilmente tipeado, mientras que otros lenguajes que proporcionan solo unas pocas conversiones pueden terminar siendo considerado fuertemente tipado.

Sin embargo, estoy inclinado a creer que debo estar equivocado en esta interepretación, simplemente no sé por qué o cómo explicarlo.

Entonces, mis preguntas son:

  • ¿Qué significa realmente para un lenguaje estar realmente débilmente tipado?
  • ¿Podría mencionar algún buen ejemplo de tipeo débil que no esté relacionado con la conversión automática / coacción automática realizada por el idioma?
  • ¿Puede un lenguaje estar débilmente tipeado y fuertemente tipado al mismo tiempo?

Además de lo que dijo Eric, considere el siguiente código C:

void f(void* x); f(42); f("hello");

A diferencia de idiomas como Python, C #, Java o lo que sea, lo anterior está débilmente tipado porque perdemos información de tipo. Eric señaló correctamente que en C # podemos eludir el compilador mediante conversión, diciéndole con eficacia "Sé más sobre el tipo de esta variable que usted".

¡Pero incluso entonces, el tiempo de ejecución aún comprobará el tipo! Si el yeso no es válido, el sistema de tiempo de ejecución lo atrapará y arrojará una excepción.

Con el borrado de tipo, esto no ocurre; se descarta la información del tipo. Un lanzamiento al void* en C hace exactamente eso. En este sentido, lo anterior es fundamentalmente diferente de una declaración de método C # como void f(Object x) .

(Técnicamente, C # también permite borrado de tipo mediante código inseguro o clasificación).

Esto es tan débilmente tipeado como se pone. Todo lo demás es solo una cuestión de comprobación de tipo estático frente a dinámico, es decir, del momento en que se comprueba un tipo.


Como han señalado otros, los términos "fuertemente tipado" y "débilmente tipado" tienen tantos significados diferentes que no hay una sola respuesta a su pregunta. Sin embargo, dado que usted mencionó específicamente a Perl en su pregunta, permítame intentar explicar en qué sentido Perl está débilmente tipado.

El punto es que, en Perl, no existe una "variable entera", una "variable flotante", una "variable de cadena" o una "variable booleana". De hecho, en lo que el usuario puede (generalmente) decir, no hay valores enteros, flotantes, de cadena o booleanos: todo lo que tiene son "escalares", que son todas estas cosas al mismo tiempo. Entonces puedes, por ejemplo, escribir:

$foo = "123" + "456"; # $foo = 579 $bar = substr($foo, 2, 1); # $bar = 9 $bar .= " lives"; # $bar = "9 lives" $foo -= $bar; # $foo = 579 - 9 = 570

Por supuesto, como nota correctamente, todo esto se puede ver como solo escribir coerción. Pero el punto es que, en Perl, los tipos siempre son coaccionados. De hecho, es bastante difícil para un usuario decir cuál podría ser el "tipo" interno de una variable: en la línea 2 en mi ejemplo anterior, preguntando si el valor de $bar es la cadena "9" o el número 9 es bastante sin sentido, ya que, en lo que respecta a Perl, esas son la misma cosa . De hecho, incluso es posible que un escalador de Perl tenga a la vez una cadena y un valor numérico al mismo tiempo, como es el caso de $foo después de la línea 2 anterior.

La otra cara de todo esto es que, dado que las variables de Perl están sin tipo (o, mejor dicho, no exponen su tipo interno al usuario), los operadores no pueden sobrecargarse para hacer cosas diferentes para diferentes tipos de argumentos; no se puede simplemente decir "este operador hará X para números e Y para cadenas", porque el operador no puede (no) indicar qué tipo de valores son sus argumentos.

Así, por ejemplo, Perl tiene y necesita un operador de suma numérica ( + ) y un operador de concatenación de cadenas ( . ): Como vimos anteriormente, está perfectamente bien agregar cadenas ( "1" + "2" == "3" ) o para concatenar números ( 1 . 2 == 12 ). De forma similar, los operadores de comparación numérica == != , < , > , <= , >= Y <=> comparan los valores numéricos de sus argumentos, mientras que los operadores de comparación de cadenas eq , ne , lt , gt , le , ge y cmp compararlos lexicográficamente como cadenas. Así que 2 < 10 , pero 2 gt 10 (pero "02" lt 10 , mientras que "02" == 2 ). (Tenga en cuenta que ciertos otros lenguajes, como JavaScript, intentan acomodarse a la tipificación débil de Perl y también a la sobrecarga del operador. Esto a menudo conduce a la fealdad, como la pérdida de asociatividad para + ).

(La mosca en la pomada aquí es que, por razones históricas, Perl 5 tiene algunos casos de esquina, como los operadores lógicos bit a bit, cuyo comportamiento depende de la representación interna de sus argumentos. En general, se los considera un defecto de diseño molesto, ya que la representación interna puede cambiar por razones sorprendentes, por lo que predecir exactamente lo que hacen esos operadores en una situación dada puede ser complicado).

Dicho todo esto, uno podría argumentar que Perl tiene tipos fuertes; simplemente no son del tipo de tipos que podrías esperar. Específicamente, además del tipo "escalar" discutido anteriormente, Perl también tiene dos tipos estructurados: "matriz" y "hash". Esos son muy distintos de los escalares, hasta el punto en que las variables de Perl tienen diferentes sigils indican su tipo ( $ para escalares, @ para matrices, % para hashes) 1 . Existen reglas de coerción entre estos tipos, por lo que puede escribir, por ejemplo, %foo = @bar , pero muchos de ellos son bastante con pérdida: por ejemplo, $foo = @bar asigna la longitud de la matriz @bar a $foo , no a su contenido . (Además, hay algunos otros tipos extraños, como typeglobs y controladores de E / S, que a menudo no se ven expuestos).

Además, una pequeña grieta en este bonito diseño es la existencia de tipos de referencia, que son un tipo especial de escalares (y que se pueden distinguir de los escalares normales, utilizando el operador ref ). Es posible utilizar referencias como escalares normales, pero sus valores de cadena / numéricos no son particularmente útiles, y tienden a perder su referencia especial si los modifica utilizando operaciones escalares normales. Además, cualquier variable de Perl 2 se puede bless a una clase, convirtiéndola en un objeto de esa clase; el sistema de clase OO en Perl es algo ortogonal al sistema de tipo primitivo (o sin tipo) descrito anteriormente, aunque también es "débil" en el sentido de seguir el paradigma de tipaje de pato . La opinión general es que, si se encuentra revisando la clase de un objeto en Perl, está haciendo algo mal.

1 En realidad, el sigil denota el tipo del valor al que se accede, de modo que, por ejemplo, el primer escalar en la matriz @foo se denota $foo[0] . Ver perlfaq4 para más detalles.

2 Los objetos en Perl son (normalmente) accesibles a través de referencias a ellos, pero lo que realmente se bless es la variable (posiblemente anónima) a la que apunta la referencia. Sin embargo, la bendición es de hecho una propiedad de la variable, no de su valor, así que, por ejemplo, asignar la verdadera variable bendecida a otra simplemente te da una copia poco profunda e inmerecida de ella. Ver perlobj para más detalles.


La tipificación fuerte <=> débil no solo trata del continuo sobre cuánto o qué tan poco de los valores es forzado automáticamente por el lenguaje para un tipo de datos a otro, sino qué tan fuerte o débilmente se tipean los valores reales. En Python y Java, y principalmente en C #, los valores tienen sus tipos establecidos en piedra. En Perl, no tanto, en realidad solo hay un puñado de diferentes tipos de valores para almacenar en una variable.

Vamos a abrir los casos uno por uno.

Pitón

En el ejemplo 1 + "1" Python, el operador + llama al __add__ para el tipo int dándole la cadena "1" como argumento, sin embargo, esto da como resultado NotImplemented:

>>> (1).__add__(''1'') NotImplemented

A continuación, el intérprete prueba el __radd__ de str:

>>> ''1''.__radd__(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: ''str'' object has no attribute ''__radd__''

Como falla, el operador + falla con el resultado TypeError: unsupported operand type(s) for +: ''int'' and ''str'' . Como tal, la excepción no dice mucho sobre la tipificación fuerte, pero el hecho de que el operador + no fuerce sus argumentos automáticamente al mismo tipo, es un indicador del hecho de que Python no es el lenguaje más débilmente tipado en el continuo.

Por otro lado, en Python se implementa ''a'' * 5 :

>>> ''a'' * 5 ''aaaaa''

Es decir,

>>> ''a''.__mul__(5) ''aaaaa''

El hecho de que la operación sea diferente requiere un tipado fuerte; sin embargo, lo contrario de * forzar los valores a números antes de multiplicar todavía no necesariamente hará que los valores sean débilmente tipados.

Java

El ejemplo de Java, String result = "1" + 1; funciona solo porque, por conveniencia, el operador + está sobrecargado por cadenas. El operador Java + reemplaza la secuencia con la creación de un StringBuilder (ver this ):

String result = a + b; // becomes something like String result = new StringBuilder().append(a).append(b).toString()

Este es más bien un ejemplo de tipeo muy estático, sin ninguna coerción real: StringBuilder tiene un método para append(Object) que se usa específicamente aquí. La documentación dice lo siguiente:

Añade la representación de cadena del argumento Object .

El efecto general es exactamente como si el argumento se convirtiera en una cadena mediante el método String.valueOf(Object) , y los caracteres de esa cadena se anexaron a esta secuencia de caracteres.

Where String.valueOf then

Devuelve la representación de cadena del argumento de objeto. [Devuelve] si el argumento es null , entonces una cadena igual a "null" ; de lo contrario, se obj.toString() el valor de obj.toString() .

Por lo tanto, este es un caso en el que no hay absolutamente ninguna coacción por parte del lenguaje, delegando cada preocupación en los objetos mismos.

DO#

De acuerdo con la respuesta de Jon Skeet aquí , el operador + ni siquiera está sobrecargado para la clase de string , similar a Java, esto es solo la conveniencia generada por el compilador, gracias a la tipificación fuerte y estática.

Perl

Como lo explica el perldata ,

Perl tiene tres tipos de datos incorporados: escalares, matrices de escalares y matrices asociativas de escalares, conocidos como "hash". Un escalar es una cadena única (de cualquier tamaño, limitada solo por la memoria disponible), un número o una referencia a algo (que se analizará en perlref). Las matrices normales son listas ordenadas de escalares indexadas por número, comenzando con 0. Las hashes son colecciones desordenadas de valores escalares indexados por su clave de cadena asociada.

Sin embargo, Perl no tiene un tipo de datos separado para números, booleanos, cadenas, nulos, undefined , referencias a otros objetos, etc. - solo tiene un tipo para todos estos, el tipo escalar; 0 es un valor escalar tanto como "0". Una variable escalar que se estableció como una cadena realmente puede cambiar a un número, y a partir de allí se comportará de manera diferente a "solo una cadena", si se accede en un contexto numérico . El escalar puede contener cualquier cosa en Perl, es tanto el objeto como existe en el sistema. mientras que en Python los nombres solo se refieren a los objetos, en Perl los valores escalares en los nombres son objetos modificables. Además, el sistema de Tipo Orientado a Objetos está pegado a esto: solo hay 3 tipos de datos en perl - escalares, listas y hashes. Un objeto definido por el usuario en Perl es una referencia (que es un puntero a cualquiera de los 3 anteriores) bless con un paquete: puedes tomar cualquier valor y bendecirlo en cualquier clase en el instante que desees.

Perl incluso le permite cambiar las clases de valores a capricho; esto no es posible en Python, donde para crear un valor de alguna clase necesita construir explícitamente el valor que pertenece a esa clase con el object.__new__ o similar. En Python no puedes cambiar la esencia del objeto después de la creación, en Perl puedes hacer cualquier cosa:

package Foo; package Bar; my $val = 42; # $val is now a scalar value set from double bless /$val, Foo; # all references to $val now belong to class Foo my $obj = /$val; # now $obj refers to the SV stored in $val # thus this prints: Foo=SCALAR(0x1c7d8c8) print /$val, "/n"; # all references to $val now belong to class Bar bless /$val, Bar; # thus this prints Bar=SCALAR(0x1c7d8c8) print /$val, "/n"; # we change the value stored in $val from number to a string $val = ''abc''; # yet still the SV is blessed: Bar=SCALAR(0x1c7d8c8) print /$val, "/n"; # and on the course, the $obj now refers to a "Bar" even though # at the time of copying it did refer to a "Foo". print $obj, "/n";

por lo tanto, la identidad del tipo está débilmente ligada a la variable, y se puede cambiar a través de cualquier referencia sobre la marcha. De hecho, si lo haces

my $another = $val;

/$another no tiene la identidad de clase, aunque /$val aún dará la bendita referencia.

TL; DR

Hay mucho más sobre tipeo débil en Perl que simplemente coacciones automáticas, y se trata más bien de que los tipos de los valores en sí mismos no están en piedra, a diferencia del Python, que es un lenguaje dinámicamente muy fuertemente tipado. Que python da TypeError en 1 + "1" es una indicación de que el lenguaje está fuertemente tipado, aunque el contrario de hacer algo útil, como en Java o C # no impide que sean lenguajes fuertemente tipados.


Me gustaría contribuir a la discusión con mi propia investigación sobre el tema, mientras otros comentan y contribuyen. He estado leyendo sus respuestas y siguiendo sus referencias y he encontrado información interesante. Como se sugirió, es probable que la mayor parte de esto se debata mejor en el foro de Programadores, ya que parece ser más teórico que práctico.

Desde un punto de vista teórico, creo que el artículo de Luca Cardelli y Peter Wegner titulado Acerca de los tipos, la abstracción de datos y el polimorfismo tiene uno de los mejores argumentos que he leído.

Un tipo se puede ver como un conjunto de ropa (o una armadura) que protege una representación subyacente no tipificada del uso arbitrario o involuntario. Proporciona una cubierta protectora que oculta la representación subyacente y limita la forma en que los objetos pueden interactuar con otros objetos. En un sistema sin tipo, los objetos sin tipo están desnudos porque la representación subyacente está expuesta para que todos la vean. La violación del sistema de tipo implica quitar la ropa protectora y operar directamente en la representación desnuda.

Esta afirmación parece sugerir que escribir débilmente nos permitiría acceder a la estructura interna de un tipo y manipularlo como si fuera algo más (otro tipo). Tal vez lo que podríamos hacer con un código inseguro (mencionado por Eric) o con c punteros borrados por tipos mencionados por Konrad.

El artículo continúa ...

Los idiomas en los que todas las expresiones son consistentes con el tipo se denominan lenguajes fuertemente tipados. Si un lenguaje está fuertemente tipado, su compilador puede garantizar que los programas que acepta se ejecutarán sin errores de tipo. En general, debemos esforzarnos por tipear con fuerza y ​​adoptar tipados estáticos siempre que sea posible. Tenga en cuenta que todo lenguaje estáticamente está fuertemente tipado, pero lo contrario no es necesariamente cierto.

Como tal, la tipificación fuerte significa la ausencia de errores de tipo, solo puedo suponer que la tipificación débil significa lo contrario: la posible presencia de errores de tipo. ¿En tiempo de ejecución o tiempo de compilación? Parece irrelevante aquí.

Lo curioso es que, según esta definición, un lenguaje con poderosas coerciones de tipo como Perl se consideraría fuertemente tipado, porque el sistema no está fallando, pero está tratando con los tipos coaccionándolos en equivalencias apropiadas y bien definidas.

Por otro lado, ¿podría decir que la tolerancia de ClassCastException y ArrayStoreException (en Java) e InvalidCastException , ArrayTypeMismatchException (en C #) indicaría un nivel de tipeo débil, al menos en tiempo de compilación? La respuesta de Eric parece estar de acuerdo con esto.

En un segundo artículo titulado Programación tipográfica provisto en una de las referencias proporcionadas en una de las respuestas en esta pregunta, Luca Cardelli profundiza en el concepto de violaciones de tipo:

La mayoría de los lenguajes de programación del sistema permiten violaciones de tipos arbitrarios, algunos indiscriminadamente, algunos solo en partes restringidas de un programa. Las operaciones que involucran violaciones de tipo se llaman defectuosas. Las infracciones de tipo se dividen en varias clases [entre las que podemos mencionar]:

Coerciones de valores básicos : Estas incluyen conversiones entre enteros, booleanos, caracteres, conjuntos, etc. Aquí no es necesario que se produzcan infracciones de tipo, porque se pueden proporcionar interfaces integradas para llevar a cabo las coerciones de forma tipo sonido.

Como tal, las coerciones de tipo como las provistas por los operadores podrían considerarse violaciones de tipo, pero a menos que rompan la consistencia del sistema de tipo, podríamos decir que no conducen a un sistema débilmente tipado.

En base a esto, ni Python, Perl, Java o C # están débilmente tipados.

Cardelli menciona dos vilations de tipo que considero muy bien casos de mecanografía realmente débil:

Dirección aritmética. Si es necesario, debe haber una interfaz integrada (poco sólida) que proporcione las operaciones adecuadas en direcciones y conversiones de tipo. Varias situaciones involucran punteros en el montón (muy peligrosos con la reubicación de colectores), punteros a la pila, punteros a áreas estáticas y punteros a otros espacios de direcciones. En ocasiones, la indexación de matrices puede reemplazar la aritmética de direcciones. Mapeo de memoria. Esto implica mirar un área de memoria como una matriz no estructurada, aunque contiene datos estructurados. Esto es típico de los asignadores de memoria y colectores.

Este tipo de cosas posibles en idiomas como C (mencionado por Konrad) o por medio de un código inseguro en .Net (mencionado por Eric) realmente implicaría un tipeo débil.

Creo que la mejor respuesta hasta ahora es la de Eric, porque la definición de estos conceptos es muy teórica, y cuando se trata de un lenguaje particular, las interpretaciones de todos estos conceptos pueden llevar a conclusiones diferentes y discutibles.


Un ejemplo perfecto proviene del Wikipedia :

Generalmente, la tipificación fuerte implica que el lenguaje de programación impone severas restricciones a la intermezcla que se permite que ocurra.

Mecanografía débil

a = 2 b = "2" concatenate(a, b) # returns "22" add(a, b) # returns 4

Mecanografía fuerte

a = 2 b = "2" concatenate(a, b) # Type Error add(a, b) # Type Error concatenate(str(a), b) #Returns "22" add(a, int(b)) # Returns 4

Tenga en cuenta que un lenguaje de tipeo débil puede mezclar diferentes tipos sin errores. Un lenguaje tipo fuerte requiere que los tipos de entrada sean los tipos esperados. En un lenguaje de tipos fuerte, un tipo puede convertirse ( str(a) convierte un entero en una cadena) o cast ( int(b) ).

Todo esto depende de la interpretación de tipeo.


Una tipificación débil significa, de hecho, que un alto porcentaje de tipos puede ser coaccionado implícitamente, intentando adivinar lo que el codificador pretendía.

El tipado fuerte significa que los tipos no son coaccionados, o al menos coaccionados menos.

La tipificación estática significa que los tipos de sus variables se determinan en el momento de la compilación.

Muchas personas han confundido recientemente "tipado de forma manifiesta" con "fuertemente tipado". "Manifestado tipeado" significa que declaras los tipos de tus variables explícitamente.

Python está fuertemente tipado, aunque puede usar casi cualquier cosa en un contexto booleano, y los booleanos se pueden usar en un contexto entero, y puede usar un entero en un contexto flotante. No está tipeado de forma manifiesta, porque no es necesario que declares tus tipos (excepto Cython, que no es enteramente python, aunque interesante). Tampoco está tipado estáticamente.

C y C ++ están expresamente tipadas, tipadas estáticamente y algo tipadas, porque declaras tus tipos, los tipos se determinan en tiempo de compilación, y puedes mezclar enteros y punteros, o enteros y dobles, o incluso lanzar un puntero a un tipo en un puntero a otro tipo.

Haskell es un ejemplo interesante, porque no está tipeado de forma manifiesta, sino que también está tipado estática y fuertemente.


As many others have expressed, the entire notion of "strong" vs "weak" typing is problematic.

As a archetype, Smalltalk is very strongly typed -- it will always raise an exception if an operation between two objects is incompatible. However, I suspect few on this list would call Smalltalk a strongly-typed language, because it is dynamically typed.

I find the notion of "static" versus "dynamic" typing more useful than "strong" versus "weak." A statically-typed language has all the types figured out at compile-time, and the programmer has to explicitly declare if otherwise.

Contrast with a dynamically-typed language, where typing is performed at run-time. This is typically a requirement for polymorphic languages, so that decisions about whether an operation between two objects is legal does not have to be decided by the programmer in advance.

In polymorphic, dynamically-typed languages (like Smalltalk and Ruby), it''s more useful to think of a "type" as a "conformance to protocol." If an object obeys a protocol the same way another object does -- even if the two objects do not share any inheritance or mixins or other voodoo -- they are considered the same "type" by the run-time system. More correctly, an object in such systems is autonomous, and can decide if it makes sense to respond to any particular message referring to any particular argument.

Want an object that can make some meaningful response to the message "+" with an object argument that describes the colour blue? You can do that in dynamically-typed languages, but it is a pain in statically-typed languages.


I like @Eric Lippert''s answer , but to address the question - strongly typed languages typically have explicit knowledge of the types of variables at each point of the program. Weakly typed languages do not, so they can attempt to perform an operation that may not be possible for a particular type. It think the easiest way to see this is in a function. C ++:

void func(string a) {...}

The variable a is known to be of type string and any incompatible operation will be caught at compile time.

Python:

def func(a) ...

The variable a could be anything and we can have code that calls an invalid method, which will only get caught at runtime.