Digitação gradual: “Quase todos os idiomas com um sistema de tipos estáticos também possuem um sistema de tipos dinâmicos”


20

Esta alegação de Aleks Bromfield afirma:

Quase todos os idiomas com um sistema de tipos estáticos também possuem um sistema de tipos dinâmicos. Além de C, não consigo pensar em uma exceção

Esta é uma reivindicação válida? Entendo que, com as classes Reflection ou Loading em tempo de execução, o Java fica um pouco assim - mas essa ideia de 'digitação gradual' pode ser estendida a um grande número de linguagens?


Não sou especialista em idiomas, mas alguns que me lembram instantaneamente de que não têm tipos dinâmicos (nativamente, não estão dizendo que você não pode juntar algo neles) - Fortran, Ada, Pascal, Cobol
mattnz

4
Eu sou especialista em idiomas e não tenho certeza do que esse cara está reivindicando. "estático" e "dinâmico" são desnômeros e geralmente indicam o horário do tipo de verificação / análise (seja no momento da compilação ou no tempo de execução). Alguns idiomas conciliam ambos (por exemplo, proibindo operações em tipos não suportados durante a compilação e gerando exceções como ClassCastException durante o tempo de execução), e isso pode ser o que ele quer dizer. Nesse caso, é verdade que C geralmente não executa verificação de tipo durante o tempo de execução. Dizendo um lang. não tem "sistema de tipo dinâmico" não faz sentido.
Thiago Silva

Respostas:


37

Tweeter original aqui. :)

Primeiro de tudo, estou um pouco divertido / chocado que meu tweet esteja sendo levado tão a sério! Se eu soubesse que isso seria amplamente divulgado, eu teria passado mais de 30 segundos escrevendo!

Thiago Silva está correto ao apontar que "estático" e "dinâmico" descrevem com mais precisão a verificação de tipos , em vez de sistemas de tipos . De fato, também não é preciso dizer que um idioma é digitado estaticamente ou dinamicamente. Em vez disso, uma linguagem possui um sistema de tipos, e uma implementação dessa linguagem pode impor o sistema de tipos usando verificação estática ou dinâmica, ou ambas, ou nenhuma das duas (embora isso não seja uma implementação de linguagem muito atraente!).

Por acaso, existem certos sistemas de tipos (ou recursos de sistemas de tipos) que são mais passíveis de verificação estática e existem certos sistemas de tipos (ou recursos de sistemas de tipos) que são mais passíveis de verificação dinâmica. Por exemplo, se seu idioma permitir que você especifique no texto de um programa que um valor específico sempre deve ser uma matriz de números inteiros, é razoavelmente simples escrever um verificador estático para verificar essa propriedade. Por outro lado, se o seu idioma tiver subtipagem e se permitir downcasting, é razoavelmente simples verificar a validade de um downcast em tempo de execução, mas extremamente difícil fazê-lo em tempo de compilação.

O que realmente quis dizer com meu tweet é simplesmente que a grande maioria das implementações de idiomas realiza alguma verificação dinâmica de tipo. Ou, equivalente, a grande maioria dos idiomas possui alguns recursos que são difíceis (se não impossíveis) de verificar estaticamente. Downcasting é um exemplo. Outros exemplos incluem estouro aritmético, verificação de limites de matriz e verificação nula. Alguns deles podem ser verificados estaticamente em algumas circunstâncias, mas, em geral, seria difícil encontrar uma implementação de idioma que não faça nenhuma verificação no tempo de execução.

Isso não é uma coisa ruim. É apenas uma observação de que existem muitas propriedades interessantes que gostaríamos que nossos idiomas aplicassem e que realmente não sabemos como verificar estaticamente. E é um lembrete de que distinções como "tipos estáticos" versus "tipos dinâmicos" não são tão claras quanto algumas pessoas querem que você acredite. :)

Uma observação final: os termos "forte" e "fraco" não são realmente usados ​​na comunidade de pesquisa em linguagem de programação e não têm um significado consistente. Em geral, descobri que quando alguém diz que um idioma tem "digitação forte" e outro idioma tem "digitação fraca", eles estão realmente dizendo que seu idioma favorito (aquele com "digitação forte") os impede de cometer algum erro que o outro idioma (aquele com "digitação fraca") não - ou, inversamente, que seu idioma favorito (aquele com "digitação fraca") permita que eles façam algo interessante que o outro idioma (o um com "digitação forte") não.


9
"É apenas uma observação de que existem muitas propriedades interessantes que gostaríamos que nossos idiomas aplicassem e que realmente não sabemos como verificar estaticamente". - Bem, não é apenas que não sabemos como fazê-lo. "Será que este impasse programa para esta entrada" é uma propriedade interessante que não só não sei como verificar, mas na verdade nós fazer saber é impossível de verificar.
Jörg W Mittag

"Outros exemplos incluem estouro aritmético, verificação de limites de matriz e verificação nula". Apenas observe que, embora existam alguns idiomas que verificam essas propriedades no sistema de tipos, mesmo nos idiomas de tipo mais dinâmico, esses geralmente são um recurso de valores , não de tipos. ( "Nulo" verificação é uma característica comum dos sistemas de tipo estático embora.)
porglezomp

Não é um tipo dinâmico do sistema , e um tipo de estática do sistema . Mesmo que nenhum deles seja imposto, eles ainda estão lá, descrevendo o que é correto e o que é um erro. O idioma / implementação pode ou não verificar nenhum deles. BTW, o sistema de tipo estático e dinâmico deve ser consistente, mas não é o caso por definição .
Elazar

Todo idioma possui um sistema de tipo dinâmico, que é um conjunto de regras que proíbe a execução de determinadas operações.
Elazar

7

Bem, sim. Você pode ter bolsas de propriedades em qualquer idioma digitado estaticamente. A sintaxe será terrível e, ao mesmo tempo, você obterá todas as desvantagens do sistema digitado dinamicamente. Portanto, não há realmente nenhuma vantagem, a menos que o compilador permita que você use uma sintaxe melhor, algo como o C # dynamicestá fazendo.

Além disso, você também pode fazer isso com facilidade em C.

Em reação a outras respostas: acho que as pessoas estão confundindo digitação estática / dinâmica com digitação forte / fraca. A digitação dinâmica é sobre ser capaz de alterar a estrutura dos dados em tempo de execução e o código é capaz de usar dados que se encaixam apenas no que o código precisa. Isso se chama Duck Typing .

Mencionar a reflexão não é contar a história toda, porque a reflexão não permite alterar a estrutura de dados existente. Você não pode adicionar um novo campo a uma classe ou estrutura em C, C ++, Java ou C #. Em linguagens dinâmicas, a adição de novos campos ou atributos às classes existentes não é apenas possível, mas também bastante comum.

Por exemplo, veja o Cython , o compilador Python-para-C. Ele cria código C estático, mas o sistema de tipos ainda mantém sua natureza dinâmica. C é uma linguagem de tipo estaticamente, mas é capaz de suportar a digitação dinâmica do Python.


Tecnicamente, você pode fazê-lo em C # a partir da versão 4 com ExpandoObject, embora seja um processo de aceitação, muito diferente do JavaScript ou Ruby. Ainda assim, você fez uma observação muito importante: a digitação com patos (o que 99% dos desenvolvedores realmente querem dizer quando dizem "digitados dinamicamente") e reflexão não são as mesmas coisas.
Aaronaught

Também posso acrescentar que o Python não possui digitação real de pato. Ele só tem alguns ganchos para você "implementar o seu próprio" (possui um método mágico que pode retornar Truepara dizer "esse objeto maluco é uma instância da classe que estou definindo"). OCaml tem esse recurso, tanto quanto eu entendo, mas eu realmente não sei.
precisa saber é o seguinte

6

Linguagens dinâmicas são linguagens estáticas . O que é comumente chamado de "digitação dinâmica" é realmente um caso especial de digitação estática - o caso em que você se restringiu a ter apenas um tipo. Como um experimento mental, imagine escrever um programa em Java ou C # usando apenas Objectvariáveis ​​/ campos / parâmetros e fazer a conversão imediatamente antes de chamar qualquer método. Seria mais preciso chamar linguagens como Python ou Javascript "unificadas". (Essa alegação provavelmente confundirá / incomodará muitas pessoas, considerando que um programa Java ou C # usaria muitos subtipos, mas isso ocorre porque a linguagem OOP média confunde tipos e classes. Leia a postagem do blog para obter mais detalhes.)

Observe que mesmo C possui digitação "dinâmica" - você pode converter qualquer ponteiro para um ponteiro void(e se a memória me servir char) e voltar. E observe também que não há verificação de tempo de execução lá; se você errar, aproveite seu comportamento indefinido!


Mas o elenco é feito estaticamente. Não vejo como esse é um exemplo de digitação dinâmica.
Osa

@osa Só porque o código diz String foo = (String) barque não significa que baré de fato a String. Você só pode saber isso em tempo de execução, então não vejo como o elenco é feito "estaticamente".
Doval

Eu não concordo com isso. Pelo menos em Javascript, você pode adicionar novos métodos e propriedades a objetos em tempo de execução. Em C #, você precisa usar explicitamente um dynamicobjeto para fazer isso. Se você tentar adicionar uma propriedade a um object... bem, não poderá.
Arturo Torres Sánchez

3

A diferença entre a digitação estática e a dinâmica é quando o tipo de um valor é verificado: tempo de compilação versus tempo de execução. Nas linguagens em que os valores carregam seu tipo com eles (por exemplo, objetos Java), você sempre pode recorrer à digitação dinâmica, mesmo quando a linguagem realmente prefere a digitação estática. Aqui está um exemplo em Java, com um método digitado dinamicamente:

void horribleJava(List untypedList) {
  for (Object o : untypedList)
    ((SpecificType) o).frobnicate();
}

Observe como o tipo de cada item é verificado no tempo de execução. O método equivalente estaticamente digitado é:

void goodJava(List<SpecificType> typedList) {
  for (SpecificType o : typedList) {
    o.forbnicate();
  }
}

Em C, valores (e especificamente ponteiros) não retêm seu tipo durante o tempo de execução - todo ponteiro é equivalente a void *. Em vez disso, variáveis e expressões têm um tipo. Para obter uma digitação dinâmica, você deve carregar as informações de tipo (por exemplo, como um campo em uma estrutura).


1
Eu não acho que um elenco conta como digitação dinâmica em qualquer sentido realmente prático. Ainda requer conhecimento do tipo em tempo de compilação, apenas adia a validação real até o tempo de execução. Você não pode invocar o frobnicatemétodo aqui sem primeiro conhecer SpecificType.
Aaronaught

2
@Aaronaught Mas isso é digitação dinâmica, uma vez que adiamos a verificação de tipo para o tempo de execução. Observe que ambos os meus exemplos usam digitação nominativa que requer um nome de tipo específico. Você está pensando em tipagem estrutural , por exemplo, tipagem de pato, que requer a presença de algum método. Os eixos estrutural versus nominativo e estático versus dinâmico são ortogonais entre si (Java é nominativo e principalmente estático; ML e Go são estruturais e estáticos; Perl, Python e Ruby são (principalmente) estruturais e dinâmicos).
amon

Como eu disse no meu último comentário, é uma distinção teórica que nenhum programador que eu já conheci realmente se importa. Você pode argumentar abrasivamente que as pessoas estão usando a terminologia errada (e de fato parece que o tweeter original estava precisando exatamente desse tipo de insensatez), mas para as pessoas que estão realmente nas trincheiras, digitação dinâmica = digitação de pato. De fato, essa definição é tão comum que idiomas como C # a codificaram (ou seja, com a dynamicpalavra - chave). Igualar estático ao tempo de compilação e dinâmico ao tempo de execução principalmente apenas atrapalha as águas.
Aaronaught

@Aaronaught: se alguém lança em uma interface, e se as classes que implementam um método com o significado pretendido implementam consistentemente a mesma interface para dizer isso, então uma é basicamente a digitação por pato em tempo de execução. Enquanto alguns podem argumentar que "digitação de pato" deveria apenas usar o nome do método, acho que seria mais útil considerar o nome do método "real" como sendo o nome da interface mais o nome do método. Caso contrário, deve [1,2].Add([3,4])produzir [1,2,3,4], [1,2,[3,4]]ou [4,6]?
Supercat

@ supercat: Nenhuma das opções acima, deve falhar porque não há Addmétodo na matriz que aceite uma matriz porque esse método seria ambíguo. A digitação com patos não o dispensa de escrever tipos e funções compreensíveis.
Aaronaught 28/01

2

A digitação estática versus dinâmica refere-se basicamente a como os tipos são verificados. A digitação estática significa que a verificação dos tipos de várias variáveis ​​ou expressões é verificada com base no código real (geralmente pelo compilador), enquanto em um sistema de tipo dinâmico essa verificação é realizada apenas em tempo de execução, pelo ambiente de tempo de execução.

O que eu acredito que o texto está se referindo é que, mesmo que os tipos sejam realmente verificados estaticamente, eles também são verificados em tempo de execução, ou seja, dinamicamente. Você mencionou corretamente o Java Reflection; a reflexão ocorre apenas no tempo de execução e o Java Runtime Environment (JVM) realmente executa a verificação de tipo quando a reflexão é usada, o que basicamente significa a verificação dinâmica de tipo.


Então não está correto. No C ++, Pascal, Fortran --- em qualquer linguagem compilada --- os tipos são verificados apenas estaticamente e não dinamicamente (a menos que você esteja usando dynamic_cast). Você pode usar ponteiros para escrever coisas arbitrárias na memória, e ninguém saberá os tipos. Portanto, a digitação estática significa SOMENTE VERIFICAR ESTÁTICAMENTE, enquanto a digitação dinâmica significa SOMENTE VERIFICAR EM EXECUÇÃO.
Osa

-1

A exceção está errada: C também possui um importante sistema de tipos dinâmicos. Simplesmente não verifica ("C é fortemente tipado, fracamente verificado"). Por exemplo, tratar uma estrutura como um double( reinternpret_castestilo) gera comportamento indefinido - um erro de tipo dinâmico.


(Para quem downvoted - O comentário de @Thiago Silva diz sobre a mesma coisa)
Elazar
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.