En busca de aclaraciones sobre las contradicciones aparentes con respecto a los idiomas débilmente mecanografiados


Creo que entiendo la tipificación fuerte, pero cada vez que busco ejemplos de lo que es la tipificación débil termino encontrando ejemplos de lenguajes de programación que simplemente coaccionan/convierten tipos automáticamente.

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

Python

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 consideres débilmente mecanografiados solo por eso.

Java

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

C#

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 se escribe débilmente 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

Así que el mismo ejemplo hace que Perl se escriba débilmente, pero no Java y C#?.

Vaya, esto es confuso introduzca la descripción de la imagen aquí

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

Por lo tanto, en algún momento me he sentido incitado a creer que si un idioma proporciona muchas conversiones automáticas o coerción entre tipos (como perl) puede terminar siendo considerado débilmente escrito, mientras que otros idiomas que proporcionan solo unas pocas conversiones pueden terminar siendo considerados fuertemente escribir.

Me inclino a creer, sin embargo, que debo estar equivocado en esta interpretación, simplemente no sé por qué o cómo explicarlo.

Entonces, mis preguntas son:

  • ¿Qué significa realmente que un lenguaje sea verdaderamente débilmente escrito?
  • ¿Podría mencionar algún buen ejemplo de tipeo débil que no esté relacionado con la conversión automática/coerción automática realizada por el lenguaje?
  • ¿Puede un lenguaje ser tipeado débilmente y fuertemente al mismo tiempo tiempo?
Author: peter-b, 2012-03-29

9 answers

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 lenguaje sea "débilmente escrito"?

Significa "este lenguaje usa un sistema de tipos que encuentro desagradable". Un lenguaje "fuertemente tipeado" por el contrario es un lenguaje con un sistema de tipos que encuentro agradable.

Los términos son esencialmente sin sentido y usted debe evitarlos. Wikipedia listas once significados diferentes para "fuertemente tipeado", varios de los cuales son contradictorios. Esto indica que las probabilidades de que se cree confusión son altas en cualquier conversación que involucre el término "fuertemente mecanografiado" o "débilmente mecanografiado".

Todo lo que realmente se puede decir con certeza es que un lenguaje "fuertemente escrito" bajo 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 un lenguaje "débilmente escrito" bajo discusión carece. Lo es posible que esa restricción no pueda determinarse sin un contexto más amplio.

En lugar de usar "fuertemente mecanografiado" y "débilmente mecanografiado", debe describir en detalle qué tipo de seguridad de tipo quiere decir. Por ejemplo, C # es un lenguaje estáticamente tipeado y un lenguaje type safe y un lenguaje memory safe, en su mayor parte. C# permite que se violen las tres formas de escritura" fuerte". El operador cast viola la tipificación estática; le dice a la compilador "Sé más sobre el tipo de tiempo de ejecución de esta expresión que tú". Si el desarrollador está equivocado, entonces 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 apagando el sistema de seguridad de tipo haciendo un bloque "inseguro". En un bloque inseguro puede usar pointer magic para tratar a un int como un flotador (violando la seguridad de tipo) o para escribir en una memoria que no posee. (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 tipeado" en comparación con los lenguajes que hacen menos comprobación en tiempo de compilación o menos comprobación en tiempo de ejecución. C# también le permite en circunstancias especiales hacer una ejecución final alrededor de esas restricciones, por lo que es un lenguaje "débilmente escrito" en comparación con los lenguajes que no le permiten hacer una ejecución final.

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

 206
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-20 19:03:09

Como otros han señalado, los términos "fuertemente mecanografiado" y "débilmente mecanografiado" 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 tratar de explicar en qué sentido Perl se escribe débilmente.

El punto es que, en Perl, no hay tal cosa como una "variable entera", una "variable flotante", una "variable de cadena" o una "variable booleana". De hecho, por lo que el usuario puede (generalmente) decir, no hay even integer, float, string or boolean values: todo lo que tienes son "escalares", que son todas estas cosas al mismo tiempo. Así que 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 usted nota correctamente, todo esto puede ser visto como un tipo de coerción. Pero el punto es que, en Perl, los tipos son siempre 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 que la cadena "9" o el número 9 no tiene sentido, ya que, en lo que respecta a Perl, esos son lo mismo. De hecho, es incluso posible que un escalar de Perl tenga internamente tanto una cadena y un valor numérico al mismo tiempo, como es por ejemplo el caso de $foo después de la línea 2 anterior.

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

Así, por ejemplo, Perl tiene y necesita tanto un operador de suma numérica (+) como un operador de concatenación de cadenas (.): como has visto anteriormente, está perfectamente bien agregar cadenas ("1" + "2" == "3") o concatenar números (1 . 2 == 12). Del mismo modo, los operadores de comparación numérica ==, !=, <, >, <=, >= y <=> comparar los valores numéricos de sus argumentos, mientras que la cadena de operadores de comparación 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 acomodar la tipificación débil similar a Perl mientras también hacen una sobrecarga de operadores. Esto a menudo conduce a la fealdad, como la pérdida de asociatividad para +.)

(La mosca en el ungüento aquí es que, por razones históricas, Perl 5 tiene algunos casos de esquina, como los operadores lógicos de bits, cuyo comportamiento depende de la representación interna de sus argumentos. Estos generalmente se consideran un defecto de diseño molesto, ya que la representación interna puede cambiar por razones sorprendentes, por lo que predecir lo que hacen esos operadores en una situación dada puede ser complicado.)

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

También, una ligera grieta en este bonito diseño es la existencia de tipos de referencia, que son un tipo especial de escalares (y que puede distinguirse de los escalares normales, utilizando el ref operador). Es posible usar referencias como escalares normales, pero sus valores de cadena/numéricos no son particularmente útiles, y tienden a perder su referencia especial si las modifica usando operaciones escalares normales. Además, cualquier variable Perl2 puede ser blessed 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 typelessness) descrito anteriormente, aunque también es "débil" en el sentido de siguiendo el paradigma duck typing. La opinión general es que, si te encuentras revisando la clase de un objeto en Perl, estás haciendo algo mal.


1 En realidad, el sigilo denota el tipo del valor al que se accede, de modo que, por ejemplo, el primer escalar en el array @foo se denota $foo[0]. Véase perlfaq4 para más detalles.

2 Objetos en Perl son (normalmente) accedidos a través de referencias a ellos, pero lo que realmente gets blessed es la variable (posiblemente anónima) a la que se refieren los puntos de referencia. Sin embargo, la bendición es de hecho una propiedad de la variable, no de su valor, por lo que, por ejemplo, asignar la variable bendita real a otra solo te da una copia superficial y no bendecida de ella. Ver perlobj para más detalles.

 63
Author: Ilmari Karonen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 05:37:11

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

void f(void* x);

f(42);
f("hello");

A diferencia de lenguajes como Python, C#, Java o lo que sea, lo anterior se escribe débilmente porque perdemos información de tipo. Eric señaló correctamente que en C# podemos eludir el compilador mediante casting, diciéndole efectivamente "Sé más sobre el tipo de esta variable que tú".

¡Pero incluso entonces, el tiempo de ejecución todavía comprobará el tipo! Si el cast no es válido, el sistema de tiempo de ejecución atrápalo y lanza una excepción.

Con el borrado de tipo, esto no sucede – la información de tipo es desechada. Un molde a void* en C hace exactamente eso. En este sentido, lo anterior es fundamentalmente diferente de una declaración del método C# como void f(Object x).

(Técnicamente, C# también permite el borrado de tipos a través de código inseguro o marshalling.)

Este está tan débilmente escrito como se obtiene. Todo lo demás es solo una cuestión de comprobación de tipo estático vs. dinámico, es decir, del tiempo cuando se comprueba un tipo.

 19
Author: Konrad Rudolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-29 23:12:38

Un ejemplo perfecto viene de el artículo de wikipedia de Strong Typing :

La tipificación generalmente fuerte implica que el lenguaje de programación impone severas restricciones en la mezcla que se permite que ocurra.

Tipificación débil

a = 2
b = "2"

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

Escritura 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

Observe que un lenguaje de escritura débil puede mezclar diferentes tipos sin errores. Un lenguaje de tipo fuerte requiere que los tipos de entrada sean los tipos esperados. En un fuerte un tipo puede ser convertido (str(a) convierte un entero en una cadena) o fundido (int(b)).

Todo esto depende de la interpretación de la escritura.

 14
Author: SaulBack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 00:44:53

Me gustaría contribuir a la discusión con mi propia investigación sobre el tema, ya que otros comentan y contribuyen He estado leyendo sus respuestas y siguiendo sus referencias y he encontrado información interesante. Como se ha sugerido, es probable que la mayor parte de esto se discuta 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 nombrado En Comprender Tipos, Abstracción de Datos y Polimorfismo tiene uno de los mejores argumentos que he leído.

Un tipo puede ser visto como un conjunto de ropa (o una armadura) que protege una representación subyacente no tipificada de uso no intencionado. Proporciona una cubierta protectora que oculta la representación subyacente y restringe la forma en que los objetos pueden interactuar con otros objetos. En un sistema sin tipo los objetos sin tipo son desnudos en eso la representación subyacente está expuesta para que todos la vean. Violar el sistema de tipo implica la eliminación del conjunto de protección de ropa y operar directamente sobre la representación desnuda.

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

El el artículo continúa...

Se llaman los lenguajes en los que todas las expresiones son compatibles con el tipo idiomas fuertemente mecanografiados. Si un lenguaje está fuertemente escrito su compilador puede garantizar que los programas que acepta se ejecutarán sin tipo error. En general, debemos esforzarnos por escribir fuerte, y adoptar tipeo estático siempre que sea posible. Tenga en cuenta que cada estáticamente el lenguaje está fuertemente escrito, pero lo contrario no es necesariamente cierto.

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

Lo curioso, 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, sino que está tratando con los tipos forzándolos a equivalencias apropiadas y bien definidas.

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

En un segundo artículo llamado Typeful Programming proporcionado en una de las referencias proporcionadas en una de las respuestas a 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 tipo arbitrarias, algunos indiscriminadamente, algunos solo en partes restringidas de un programa. Las operaciones que involucran violaciones de tipo se denominan no sólidas. Tipo las violaciones caen en varias clases [entre las cuales podemos mencionar]:

Coerciones de valores básicos: Estas incluyen conversiones entre enteros, booleanos, caracteres, conjuntos, etc. No hay necesidad de violaciones de tipo aquí, porque las interfaces incorporadas se pueden proporcionar para llevar a cabo el coerciones en una forma de sonido de tipo.

Como tal, escriba las coerciones como las proporcionadas 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 tipeado.

Basado en esto ni Python, Perl, Java o C# están débilmente escritos.

Cardelli menciona dos tipos de vilaciones que considero muy bien los casos de tipificación verdaderamente débil:

Aritmética de direcciones. Si es necesario, debe haber una interfaz incorporada (no sólida) , proporcionar las operaciones adecuadas en las direcciones y conversiones de tipo. Varias situaciones implican punteros en el montón (muy peligroso con la reubicación de los colectores), punteros a la apilar, punteros a áreas estáticas y punteros a otra dirección espacio. A veces, 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 Coleccionista.

Este tipo de cosas posibles en lenguajes como C (mencionado por Konrad) o a través de código inseguro en.Net (mencionado por Eric) implicaría realmente escribir débilmente.

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 en particular, las interpretaciones de todos estos conceptos pueden llevar a diferentes conclusiones discutibles.

 4
Author: Edwin Dalorzo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-30 18:44:46

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

La tipificación 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 tiempo de compilación.

Muchas personas han estado confundiendo recientemente "manifiestamente mecanografiado" con "fuertemente mecanografiado". "Manifiestamente tipado" significa que declara los tipos de sus variables explícitamente.

Python en su mayoría se escribe fuertemente, 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á manifiestamente escrito, porque no necesitas declarar tus tipos (excepto Cython, que no es enteramente python, aunque interesante). Tampoco se escribe estáticamente.

C y C++ están manifiestamente tipeados, estáticamente tipeados y algo fuertemente tipeados, porque declaras tus tipos, los tipos están determinados en tiempo de compilación, y puede mezclar enteros y punteros, o enteros y dobles, o incluso convertir un puntero a un tipo en un puntero a otro tipo.

Haskell es un ejemplo interesante, porque no se escribe manifiestamente, pero también se escribe estática y fuertemente.

 4
Author: user1277476,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-18 16:53:49

El strong weak typing no solo trata sobre el continuo de cuánto o qué tan poco de los valores son coaccionados automáticamente por el lenguaje para un tipo de datos a otro, sino sobre qué tan fuerte o débilmente se teclean los valores reales . En Python y Java, y sobre todo en C#, los valores tienen sus tipos establecidos en piedra. En Perl, no tanto, en realidad solo hay un puñado de tipos de valor diferentes para almacenar en una variable.

Abramos los casos uno por una.


Python

En Python ejemplo 1 + "1", + el operador llama a __add__ para el tipo int dándole la cadena "1" como argumento-sin embargo, esto resulta en NotImplemented:

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

A continuación, el intérprete intenta 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__'

Cuando 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 escritura fuerte, pero el hecho de que el operador + no coacciona sus argumentos automáticamente al mismo tipo, es un puntero al hecho de que Python no es el lenguaje de tipo más débil en el continuum.

Por otro lado, en Python 'a' * 5 is implemented:

>>> 'a' * 5
'aaaaa'

Es decir,

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

El hecho de que la operación es diferente requiere un tipo fuerte-sin embargo, lo contrario de * coaccionar los valores a números antes de multiplicar aún no necesariamente haría que los valores sean débiles escribir.


Java

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

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 coerción real - StringBuilder tiene un método append(Object) eso se usa específicamente aquí. La documentación dice lo siguiente:

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

El efecto general es exactamente como si el argumento se convirtiera en un cadena por el método String.valueOf(Object), y los caracteres de esa cadena se añadió a esta secuencia de caracteres.

Donde String.valueOf entonces

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

Por lo tanto, este es un caso de absolutamente ninguna coacción por parte del lenguaje - delegando toda preocupación a los objetos mismos.


C #

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


Perl

Como el perldata explica,

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

Perl sin embargo no tiene un tipo de datos separado para números, booleanos, cadenas, nulos, undefined s, 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 de ahí en adelante comportarse de manera diferente de "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. considerando que en Python los nombres solo se refieren a los objetos, en Perl los valores escalares en los nombres son objetos cambiables. Además, el sistema de Tipos Orientados a objetos está pegado a esto: solo hay 3 tipos de datos en escalares, listas y hashes de perl. Un objeto definido por el usuario en Perl es una referencia (que es un puntero a cualquiera de los 3 anteriores) blessed a un paquete - puede tomar cualquier valor y bendecirlo a cualquier clase en cualquier momento que desee.

Perl incluso le permite cambiar las clases de valores a su antojo - 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 object.__new__ o similar. En Python realmente no se puede cambiar la esencia del objeto después de la creación, en Perl se puede hacer mucho 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 de 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 clase identidad, aunque \$val todavía dará la referencia bendita.


TL; DR{[47]]}

Hay mucho más acerca de la tipificación débil a Perl que solo coerciones automáticas, y se trata más de que los tipos de los valores en sí no se establecen en piedra, a diferencia del Python que es dinámicamente pero muy fuertemente escrito lenguaje. Que python da TypeError en 1 + "1" es una indicación de que el lenguaje está fuertemente escrito, aunque lo contrario de hacer algo útil, como en Java o C# no excluye que sean lenguajes fuertemente tipeados.

 3
Author: Antti Haapala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:46:21

Me gusta la respuesta de@Eric Lippert, pero para abordar la pregunta - los lenguajes fuertemente tipeados típicamente tienen conocimiento explícito de los tipos de variables en cada punto del programa. Los lenguajes con tipos débiles no lo hacen, por lo que pueden intentar realizar una operación que puede no ser posible para un tipo en particular. Creo que la forma más fácil de ver esto es en una función. C++:

void func(string a) {...}

Se sabe que la variable a es de tipo string y cualquier operación incompatible será capturada en tiempo de compilación.

Python:

def func(a)
  ...

La variable a podría ser cualquier cosa y podemos tener código que llama a un método no válido, que solo se capturará en tiempo de ejecución.

 0
Author: Lubo Antonov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:15

Como muchos otros han expresado, toda la noción de mecanografía "fuerte" vs "débil" es problemática.

Como arquetipo, Smalltalk se escribe muy fuertemente { siempre generará una excepción si una operación entre dos objetos es incompatible. Sin embargo, sospecho que pocos en esta lista llamarían a Smalltalk un lenguaje fuertemente escrito, porque es dinámicamente escrito.

Encuentro la noción de tipeo "estático" versus "dinámico" más útil que "fuerte" versus "débil." Un estáticamente lenguaje escrito tiene todos los tipos descubierto en tiempo de compilación, y el programador tiene que declarar explícitamente si de lo contrario.

Contraste con un lenguaje de escritura dinámica, donde la escritura se realiza en tiempo de ejecución. Esto es típicamente un requisito para lenguajes polimórficos, por lo que las decisiones sobre si una operación entre dos objetos es legal no tienen que ser decididas por el programador de antemano.

En lenguajes polimórficos de tipo dinámico (como Smalltalk y Ruby), es más útil pensar en un " tipo "como una" conformidad con el protocolo."Si un objeto obedece a un protocolo de la misma manera que otro objeto does incluso si los dos objetos no comparten ninguna herencia o mixins u otro vudú they se consideran del mismo "tipo" por el sistema de tiempo de ejecución. Más correctamente, un objeto en tales sistemas es autónomo, y puede decidir si tiene sentido responder a cualquier mensaje en particular que se refiera a cualquier argumento en particular.

Quiere un objeto que pueda hacer algo significativo respuesta al mensaje "+" con un argumento de objeto que describe el color azul? Puedes hacer eso en lenguajes tipeados dinámicamente, pero es un dolor en lenguajes tipeados estáticamente.

 0
Author: Jan Steinman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 18:09:58