Como um sistema de tipo estático afeta o design de uma linguagem baseada em protótipo?

15

O artigo da Wikipedia sobre idiomas baseados em protótipos contém o seguinte parágrafo:

Quase todos os sistemas baseados em protótipos são baseados em linguagens interpretadas e de tipo dinâmico. Sistemas baseados em linguagens estaticamente tipadas são tecnicamente viáveis, no entanto.

De que maneira um sistema de tipo estático impõe restrições ou introduz complexidade na linguagem baseada em protótipo e por que existem linguagens de protótipo mais dinamicamente tipadas?

Joe
fonte
2
+1 e favorito: estou pensando nisso há um bom tempo e não encontrei nenhum problema extraordinariamente difícil com um sistema de tipo estrutural . Na verdade, isso me incomoda tanto que eu quero em frente e tentar criar uma linguagem baseada em protótipo estaticamente digitado só para ver quais os problemas que existem ...
Eu estou apenas começando esse processo me pela mesma razão :)
Joe

Respostas:

6

A fronteira entre um tipo fundamental e um objeto é borrada e frequentemente introduzida artificialmente. Por exemplo, em C, uma estrutura é apenas um monte de registros, apenas um tipo não-objeto derivado. Em C ++, uma estrutura é uma classe com todos os campos públicos, um objeto. Ainda assim, C ++ é quase totalmente compatível com C ... a borda é realmente suave aqui.

Para programação baseada em protótipo, você precisa ter objetos mutáveis ​​em tempo de execução. Eles DEVEM ser digitados manualmente, porque cada um muda em tempo de execução, uma classe de um tipo muda para outra - seu tipo é alterado.

Você pode manter os tipos não-objetos fundamentais e derivados como estáticos. Mas isso introduz uma disparidade estranha, os objetos são de tipo suave, os não-objetos são de estática e um barier rígido deve ser estabelecido entre os dois. Você deve ser capaz de transformar uma estrutura? Uma linha? Number deve ser uma classe ou um tipo fundamental, ou um conjunto de tipos fundamentais, int / float / bignum / etc?

É apenas mais natural e fácil de aprender, usar e escrever para ter esse uniforme, todos os tipos são mutáveis ​​ou nenhum tipo é mutável em tempo de execução. Se você declarar que apenas um tipo (Objeto) é mutável, você terá dores de cabeça e problemas nos dois mundos.

O tipo estático é:

  • mais fácil de implementar
  • mais rápido / mais eficiente
  • mais segura
  • mais fácil de manter / documentar grandes sistemas devido à abstração.

O tipo dinâmico é:

  • mais rápido para escrever,
  • mais conciso
  • idioma mais fácil de aprender
  • mais tolerante por erros de design.

Ao misturar os dois, você sacrifica muito.

  • A implementação se torna mais difícil do que qualquer uma das duas anteriores.
  • a velocidade depende se você usa os tipos flexíveis ou não ... Se você usa, é baixo, se não usa, por que escolher o idioma?
  • A segurança de tipos está fora da janela para todos os tipos de objetos.
  • seguir como um tipo se transforma em outro é uma tarefa bastante difícil. Documentando - muito difícil.
  • Você ainda precisa fazer toda a contabilidade com tipos fundamentais, o que reduz a concisão e a velocidade de gravação
  • A complexidade do idioma é maior (mais difícil de aprender) do que qualquer um dos "específicos",
  • o "perdão" de um tipo dinâmico é substituído pela tendência a alguns erros muito complicados em tipos de atributos incompatíveis.
SF.
fonte
1
Lembre-se de fornecer um exemplo de por que os objetos precisam ser "mutáveis" (suponho que você queira dizer adição e remoção de atributos, não alterá-los, pois isso geralmente não está relacionado à digitação).
@ delnan: na verdade, na programação baseada em protótipos, você pode cavar as entranhas de um objeto como achar melhor, remover, adicionar, substituir, cobrir, ambos os métodos e atributos em uma instância ao vivo. Esse é o ponto e uma substituição muito conveniente e flexível para modificar objetos através de regras rígidas de herança clássica. Se um idioma usa uma classe como um tipo, você não pode modificar sua estrutura rapidamente se o tipo não for suave.
SF.
1
Acho que não. Pela mesma lógica, alguém poderia argumentar que a programação baseada em classes precisa das mesmas liberdades que as linguagens dinâmicas baseadas em classes permitem. Não, protótipos estáticos com sistemas de tipo estrutural anotariam objetos com uma lista de seus membros e recursivamente seus tipos, e verificariam estaticamente se esses membros existem (e têm o tipo certo) exigindo que todos os membros sejam dados na criação de objetos ou presentes em o protótipo e simplesmente não incluindo uma maneira de remover membros. O resultado ainda me parece bastante protótipo e garante que cada membro esteja presente o tempo todo.
@ delnan: Você acabou de descrever a herança clássica através da composição. Sim, parece bastante prototípico e é uma maneira (muito nervosa) de fazer programação baseada em protótipo em uma linguagem clássica de modelo de herança. Apenas tira 90% da diversão, matando suas maiores vantagens (e removendo simultaneamente os maiores perigos). Sim, na antiga analogia do tiro com o pé, o pb.p com todos os recursos ajudará você a tirar as duas pernas com uma colher de chá. Se você não gosta desse tipo de poder, é melhor se ater à herança clássica.
SF.
1
Você confunde "dinâmico" com "protótipos". Essas liberdades que não se combinam bem com sistemas estáticos não são características de protótipos, são características de dinamismo. É claro que adicionar a digitação estática os impede, mas eles não fazem parte dos protótipos (isso é o IMGO, principalmente a falta de classes em favor da clonagem de objetos para agir como pais). Esse dinamismo é ortogonal aos protótipos. Todas as linguagens populares de protótipo as incluem, mas são independentes dos protótipos, como declarado anteriormente. Considere este trecho em um idioma fictício: pastebin.com/9pLuAu9F . Como não são protótipos?
3

A dificuldade é bem simples de se ver: Tendo em vista os objetos como dicionários de métodos ou como coisas que respondem a mensagens, observe o seguinte sobre linguagens OO comuns de tipo estatístico:

  • Todas as chaves / mensagens do dicionário geralmente são declaradas com antecedência, usando identificadores declarados estaticamente.

  • Certos conjuntos de mensagens são declarados com antecedência e objetos são associados a esses conjuntos para determinar a quais mensagens eles respondem.

  • Os relacionamentos de inclusão de um conjunto de mensagens sendo um subconjunto de outro são declarados estaticamente e explicitamente; não declarado, mas os subconjuntos lógicos não são válidos.

  • A verificação de tipo tenta garantir que todas as mensagens sejam enviadas apenas aos objetos que respondem a elas.

Cada um desses conflitos, em certa medida, com um sistema baseado em protótipo:

  • Os nomes das mensagens podem ser declarados antecipadamente, na forma de "átomos", seqüências de caracteres internas ou outros enfeites, mas pouco mais; a plasticidade dos objetos significa que atribuir tipos a métodos é estranho.

  • É indiscutivelmente o recurso essencial de um sistema baseado em protótipo que define os conjuntos de mensagens pelo que um objeto responde, e não o contrário. Seria razoável atribuir aliases a combinações específicas em tempo de compilação, mas os conjuntos de mensagens determinados em tempo de execução devem ser possíveis.

  • O impacto real dos dois itens acima atinge os relacionamentos de inclusão, nos quais declarações explícitas são completamente impraticáveis. A herança no sentido estático de subtipo nominal é antitética a um sistema baseado em protótipo.

O que nos leva ao ponto final, que na verdade não queremos mudar. Ainda gostaríamos de garantir que as mensagens sejam enviadas apenas aos objetos que respondem a elas. Contudo:

  • Não podemos saber estaticamente quais mensagens podem ser agrupadas.
  • Não podemos saber quais agrupamentos são subconjuntos de outros.
  • Não podemos saber quais agrupamentos são possíveis.
  • Não podemos nem especificar que tipo de argumentos são enviados junto com uma única mensagem.
  • Basicamente, descobrimos que não podemos especificar muita coisa no caso totalmente geral.

Então, como isso pode ser resolvido? Limite a generalidade total de alguma forma (o que é desagradável e pode rapidamente eliminar todos os benefícios do uso de um sistema baseado em protótipo) ou torne o sistema de tipos muito mais fluido e expresse restrições em vez de tipos exatos .

O sistema de tipos baseado em restrições rapidamente leva à noção de subtipagem estrutural , que em um sentido muito amplo pode ser considerada o equivalente estático da "tipagem de pato". Os maiores obstáculos aqui são que esses sistemas são muito mais complicados de digitar cheques e são menos conhecidos (o que significa pouco trabalho prévio para estudar).

Em resumo: é possível, é mais difícil de fazer do que um sistema de tipo estático nominal ou um sistema dinâmico baseado em metadados de tempo de execução e, portanto, poucas pessoas se incomodam.

CA McCann
fonte
1

Acredito que uma maneira de obter uma linguagem baseada em protótipo e com estaticamente seria basear a linguagem em modelos e conceitos.

Os conceitos já foram um recurso planejado para C ++ 0x. O código genérico nos modelos C ++ já é de fato "estaticamente tipado por pato". A idéia de Conceitos é poder dizer algumas coisas sobre membros necessários e características de tipos, sem exigir ou implicar um modelo de herança de classe subjacente a esse relacionamento (porque ele teve que trabalhar com o código de modelo existente que já era "estaticamente tipado" )

Em uma linguagem baseada em modelos e conceitos, os conceitos seriam baseados em protótipos, e os modelos o libertariam de se preocupar com qualquer modelo de classe que possa ou não ser usado para implementar os tipos de valores.

Além dos truques de usar a compilação faseada para permitir que a linguagem seja sua própria meta-linguagem, essas derivações prototípicas de Conceitos seriam necessariamente imutáveis ​​uma vez criadas. No entanto, a objeção de que isso não é baseado em protótipo é um arenque vermelho. Seria simplesmente uma linguagem funcional. Uma linguagem dinâmica de base de protótipo que também é funcional pelo menos foi tentada .

Dennis Ferron
fonte