A digitação forte <=> fraca não é apenas sobre o continuum de quanto ou quão pouco dos valores são coagidos automaticamente pelo idioma de um tipo de dados para outro, mas quão forte ou fracamente o real valores são digitados. Em Python e Java, e principalmente em C #, os valores têm seus tipos definidos em pedra. No Perl, nem tanto - existem realmente apenas alguns tipos diferentes de valores para armazenar em uma variável.
Vamos abrir os casos um por um.
Pitão
No exemplo do Python 1 + "1"
, o +
operador chama o __add__
tipo for, int
fornecendo a string "1"
como argumento - no entanto, isso resulta em NotImplemented:
>>> (1).__add__('1')
NotImplemented
Em seguida, o intérprete tenta o __radd__
comando str:
>>> '1'.__radd__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'
Como falha, o +
operador falha com o resultado TypeError: unsupported operand type(s) for +: 'int' and 'str'
. Como tal, a exceção não diz muito sobre digitação forte, mas o fato de o operador +
não coagir seus argumentos automaticamente para o mesmo tipo é um indicador do fato de que Python não é a linguagem de tipo mais fraco no continuum.
Por outro lado, em Python 'a' * 5
é implementado:
>>> 'a' * 5
'aaaaa'
Isso é,
>>> 'a'.__mul__(5)
'aaaaa'
O fato de a operação ser diferente requer uma digitação forte - no entanto, o oposto de *
coagir os valores a números antes de multiplicar ainda não necessariamente tornaria os valores digitados de maneira fraca.
Java
O exemplo de Java String result = "1" + 1;
funciona apenas porque, por uma questão de conveniência, o operador +
está sobrecarregado para seqüências de caracteres. O +
operador Java substitui a sequência pela criação de um StringBuilder
(consulte este ):
String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()
Este é um exemplo de digitação muito estática, sem coerção real - StringBuilder
tem um métodoappend(Object)
que é usado especificamente aqui. A documentação diz o seguinte:
Anexa a representação em cadeia do Object
argumento.
O efeito geral é exatamente como se o argumento fosse convertido em uma string pelo método String.valueOf(Object)
, e os caracteres dessa sequência foram anexados a essa sequência de caracteres.
Onde String.valueOf
então
Retorna a representação em cadeia do argumento Object. [Retorna] se o argumento for null
, então uma string igual a "null"
; caso contrário, o valor deobj.toString()
é retornado.
Portanto, este é um caso de absolutamente nenhuma coerção por parte da linguagem - delegando toda preocupação aos próprios objetos.
C #
De acordo com a resposta de Jon Skeet aqui , o operador +
nem está sobrecarregado para a string
classe - semelhante ao Java, isso é apenas uma conveniência gerada pelo compilador, graças à digitação estática e forte.
Perl
Como o perldata explica,
O Perl possui três tipos de dados internos: escalares, matrizes de escalares e matrizes associativas de escalares, conhecidas como "hashes". Um escalar é uma cadeia única (de qualquer tamanho, limitada apenas pela memória disponível), número ou uma referência a algo (que será discutido em perlref). Matrizes normais são listas ordenadas de escalares indexados por número, começando com 0. Hashes são coleções não ordenadas de valores escalares indexados por sua chave de cadeia associada.
O Perl, no entanto, não possui um tipo de dados separado para números, booleanos, seqüências de caracteres, valores nulos, undefined
s, referências a outros objetos etc. - ele só possui um tipo para todos esses, o tipo escalar; 0 é um valor escalar tanto quanto "0". Uma variável escalar que foi definida como uma string pode realmente se transformar em um número e, a partir daí, se comportar de maneira diferente de "apenas uma string", se for acessada em um contexto numérico. O escalar pode conter qualquer coisa no Perl, é o objeto que existe no sistema. enquanto em Python os nomes se referem apenas aos objetos, em Perl os valores escalares nos nomes são objetos alteráveis. Além disso, o sistema de tipo orientado a objetos é colado em cima disso: existem apenas três tipos de dados em perl - escalares, listas e hashes. Um objeto definido pelo usuário no Perl é uma referência (que é um ponteiro para qualquer um dos 3 anteriores)bless
distribuído para um pacote - você pode pegar esse valor e abençoá-lo com qualquer classe a qualquer momento que desejar.
O Perl ainda permite que você altere as classes de valores por capricho - isso não é possível no Python, para criar um valor de alguma classe, você precisa construir explicitamente o valor pertencente a essa classe object.__new__
ou similar. No Python, você não pode realmente mudar a essência do objeto após a criação; no Perl, você pode fazer qualquer coisa:
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";
assim, a identidade do tipo está fracamente ligada à variável e pode ser alterada através de qualquer referência em tempo real. De fato, se você fizer
my $another = $val;
\$another
não possui a identidade de classe, mesmo que \$val
ainda dê a referência abençoada.
TL; DR
Há muito mais sobre digitação fraca no Perl do que apenas coerções automáticas, e é mais sobre o fato de que os tipos dos valores em si não são gravados em pedra, ao contrário do Python, que é uma linguagem de tipo dinâmico e muito fortemente tipada. Que python dá TypeError
on 1 + "1"
é uma indicação de que a linguagem é fortemente tipado, embora o contrário de fazer algo útil, como em Java ou C # não impede que eles, sendo línguas rigidez.