Se você projetasse uma linguagem de programação, como faria isso? Quais recursos você colocaria? O que você deixaria de fora? Estática ou dinamicamente digitada? Tipo forte ou fraco? Compilado ou interpretado? Justifique suas respostas.
Se você projetasse uma linguagem de programação, como faria isso? Quais recursos você colocaria? O que você deixaria de fora? Estática ou dinamicamente digitada? Tipo forte ou fraco? Compilado ou interpretado? Justifique suas respostas.
Respostas:
Definitivamente, acho que as linguagens de programação funcionais continuarão, então minha linguagem será funcional. Consulte Domesticando efeitos com programação funcional
Acho que as CPUs em breve terão centenas de núcleos, e os threads serão um inferno para gerenciar. Portanto, o modelo do ator é uma obrigação, em vez de threads. Veja Erlang - software para um mundo simultâneo
Eu também acho que OOP falhou, a comunicação entre objetos foi assumida como assíncrona . Então, acho que precisamos passar mensagens , com mensagens imutáveis. Envie e esqueça. Como no modelo do ator. Consulte Programação orientada a objetos: o caminho errado?
Eu acho que seria bom ter uma digitação estática , para que os erros sejam detectados no início do ciclo de desenvolvimento. Mas eu usaria a inferência de tipo como em Haskell, para que o desenvolvedor não precise escrever o tipo em qualquer lugar do código, como em C, C # e Java. Veja Aprenda um Haskell para um grande bem
Eu também projetaria uma ótima biblioteca de interface do usuário , com layout declarativo , como no WPF e no Android. Mas eu gostaria de tê-lo como na Programação Reativa Funcional .
Portanto, minha linguagem seria semelhante à concorrência em Erlang, mas com a digitação como em Haskell e uma estrutura de GUI como no WPF.NET.
Nota: usei a sintaxe do tipo C para descrever os recursos deste post, mas não sou exigente quanto à sintaxe, desde que não seja algo ridículo, como todas as palavras-chave que são CAPS.
1. Sistema de digitação
O recurso número um que eu gostaria em um idioma é a digitação estática com a digitação dinâmica opcional . O motivo é que a digitação estática permite: a) detectar erros mais cedo do que tarde eb) a maioria dos códigos são implicitamente digitados estaticamente, independentemente de o idioma fazer ou não a distinção. No entanto, existem vários casos de uso em que a digitação dinâmica é extremamente útil. Por exemplo, ao ler dados de um arquivo, você costuma ter campos de tipos variados, e a digitação dinâmica facilita os contêineres heterogêneos. Então, minha linguagem ideal teria algo assim:
//variable declarations
int anInt = 42 //anInt is now irrevocably an integer and assigning another type to it is an error
vartype aVariable = 42 //aVariable is currently an integer, but any type can be assigned to it in the future
//function definitions
int countElements(Collection c)
{
return c.count();
}
//c HAS to be a collection, since countElements doesn't make sense otherwise
void addToCollection(Collection& c, vartype v)
{
c.append(v)
}
//c is passed by reference here
2. Compilado vs. Interpretado
Eu gostaria que o idioma fosse compilado com antecedência ou JIT, mas não puramente interpretado, sendo a velocidade a razão. Isso está relacionado ao ponto 1 , já que um compilador / jitter otimizando terá muito mais facilidade para otimizar o código digitado estaticamente, e o código digitado dinamicamente pode simplesmente ser deixado como está.
3. Encerramentos
A linguagem deve suportar construções de programação funcional e as funções devem ser objetos de primeira classe.
4. Orientado a objetos
A linguagem deve permitir que você escreva código orientado a objetos, mas também deve ser permitido um código imperativo simples. ou seja, deve ser possível escrever um programa Olá Mundo como este:
int main(string<> args=null)
{
printf("hello, world");
return 0;
}
// this code also demonstrates two other features,
// default arguments for functions (not explained further)
// and immutable lists like string<> (see 6. Built-in datatypes)
5. Namespaces
Namespaces são uma coisa boa. Muito pouca coisa deve ser inserida no espaço de nomes global. Mas se você precisar colocar coisas no espaço de nomes global, poderá (ala C ++).
6. Tipos de dados internos
O idioma deve ter, como tipos de dados internos, as seguintes construções:
int
tipo de dados ou tipos. Se houver apenas um int
tipo, ele deverá ter alcance ilimitado. Se houver mais, deve haver upcasting implícito no menor tipo capaz de conter o resultado de uma computação, sendo o tipo de alcance ilimitado o maior.float
tipo binário interno, equivalente a um IEEE 754double
list
tipo mutável que é implementado como uma lista duplamente vinculada ou como um bloco de memória contígua contendo ponteiros para cada elementolist
tipo imutável que age como uma matriz, mas cujo tamanho não pode ser alterado após a criaçãostring
Tipos mutáveis e imutáveis , com o padrão imutável.map
ou dict
que é mutável e contém chaves imutáveis e valores mutáveis e / ou imutáveis.vartype
d, se necessárioboolean
tiponull
ou none
tipo que pode ser atribuído a uma variável de qualquer tipo.set
Tipos mutáveis e imutáveisdecimal
tipo que implementa variáveis decimais de ponto flutuantefixed
tipo que implementa um número de ponto fixoOs tipos decimal
, float
e fixed
devem compartilhar exatamente a mesma interface pública (via herança ou digitação de pato), permitindo que sejam passados e retornados de forma transparente a partir de funções. O tipo pai pode ser chamado real
.
7. Chamada por valor e por referência
Você deve ser capaz de chamar funções por valor e referência, com o valor padrão (ou seja, uma cópia do argumento é feita e operada na função).
8. Ponteiros
O idioma deve ter ponteiros e permitir aritmética do ponteiro. Os ponteiros só podem ser digitados estaticamente (para evitar o pesadelo que é a void*
). vartype
ponteiros são explicitamente proibidos. Ter ponteiros e aritmética de ponteiros permite que a linguagem seja seriamente usada como linguagem de programação de sistemas.
9. Montagem em linha
Em conexão com 8. , o idioma deve permitir o código da linguagem assembly em linha para as situações em que é necessário.
10. Segurança
O idioma deve ser mais seguro de usar, suportando o tratamento de exceções etc. A montagem aritmética e embutida do ponteiro pode ser relegada para partes do código explicitamente marcadas como inseguras. Código inseguro é permitido, mas fortemente desencorajado.
11. Comportamento indefinido
O padrão da linguagem deve especificar como o programa deve se comportar em todas as circunstâncias, exceto no código explicitamente marcado como inseguro, ou seja, não deve haver comportamento indefinido fora dos blocos inseguros. Isso permite que o idioma seja usado como um idioma viável de desenvolvimento de aplicativos, enquanto ainda permite que você diga, escreva um sistema operacional nele.
É tudo o que consigo pensar no momento, mas vou editar / atualizar o post à medida que penso em mais coisas.
decimal
tipo aqui.
É assim que minha linguagem de programação dos sonhos se pareceria:
yield
no Smalltalk? Deve ser o mais limpo possível de usar.
Eu o teria projetado praticamente como C #, mas a Microsoft me superou. :)
(Exceto, é claro, que o meu teria sido menos bem pensado e mais amador.)
Não me importo muito se é compilado ou interpretado, então não preciso justificar isso.
No que diz respeito à tipagem estática forte, acho difícil entender por que isso exige justificativa. A digitação estática é um recurso que captura bugs durante o tempo de compilação. A digitação dinâmica é a falta desse recurso e adia os bugs até o tempo de execução. Na minha experiência pessoal, eu tinha poucos casos de uso em que o despacho dinâmico fazia sentido e era útil; portanto, as convoluções que tive que passar em C # antes do 4.0 para obtê-lo eram facilmente justificadas. Com o C # 4.0, nem preciso mais justificar isso, porque temos despacho dinâmico agora.
No entanto, eu provavelmente teria criado uma nova sintaxe em vez de aderir tão religiosamente à sintaxe C antiga quanto o C #. A declaração switch é particularmente horrível e também não gosto da sintaxe do elenco (é o contrário). Porém, não faço muita barulho quanto aos detalhes da sintaxe, então não preciso justificá-la em detalhes, exceto que não a quero tão detalhada quanto o Visual Basic.
O que mais você gostaria que eu justificasse?
Bem, aqui está uma lista de recursos que eu colocaria:
Estilo Lisp
Prós :
(eval "your data files")
Contras :
Estilo Haskell
Prós :
Contras :
Estilo Python
Prós :
Implementação :
Permitir sobrecarga de função com base em tipos, semelhantes aos CLs defgeneric
:
(define (+ (a <int>) (b <int>))
(ints-add a b))
(define (+ (a <string>) (b <string>))
(string-concat a b))
(define (+ a b)
(add-generic a b))
Prós :
Contras :
Estilo C
Prós :
Contras :
Prós :
Contras :
Pensando bem, esse esquema define mais ou menos, exceto o bit de compilação e programação de sistemas. Isso pode ser contornado usando libguile e escrevendo esses bits em C.
car
função e cdr
argumento são, você tem um objeto cujo name
campo é o método e cujo arguments
campo é os argumentos e em vez de nidificação, você tem. prev
e next
ponteiro campos).
Existem vários idiomas por aí que considero muito bons (C # é o meu favorito atual). Como essa é a minha linguagem de fantasia, eis o que eu realmente quero:
Estou falando mal de mim porque não sei muito sobre design de linguagem, mas acho que o recurso de que estou falando se chama dicas em outros idiomas. Dicas do compilador , talvez?
Não sei se li isso em um rascunho do Perl6 ou estava alto na época, mas imagino uma linguagem em que tudo, por padrão, é frouxo e auto-mágico. Mas se você realmente deseja aumentar o desempenho e dizer, ei, esse valor é sempre um número inteiro ou nunca é nulo, ou pode ser paralelo, ou sem estado, coisas assim ... Que o compilador poderia ir automaticamente à cidade nessas áreas especificamente marcadas.
E: Eu apreciaria comentários esclarecendo o que estou pedindo ou citando exemplos onde isso já existe.
safety
e speed
, é possível que o compilador verifique e imponha (para encontrar problemas) ou assuma que o que você diz é verdadeiro (e compile um código mais rápido).
Para experimentar novas idéias:
Eu criaria uma linguagem de programação funcional de tipo dinâmico, que permite executar todos os truques de expressão de instrução e a sintaxe lambda mais simples com correspondência de padrões. Regra externa ativada.
// a view pattern (or Active Pattern in F#)
default = \def val: !!val.Type val def
// usage of the pattern
greet = \name<(default "world") `and` hasType Str>:
p "Hello, \{name}!"
(p "Enter your name", .input).greet // (, ) is a sequence expression, returning the last value
Aqui está uma explicação:
default =
define o armazenamento, \def val
começa uma função de avaliar num com dois argumentos, val.Type
é o mesmo que Type[val]
, !!
convertidos para booleano, e booleano pode ser aplicado, por isso, val
edef are after it.
f x
= f[x]
= x.f
.f
=f[]
e em greet
, usado name<(default "world")
e hasType Str>
, significa que o padrão default "world"
será usado e vinculado name
. O padrão padrão especifica um valor padrão.
and
é outro padrão que une dois padrões. o default
padrão não pode falhar enquanto hasType
pode falhar. Nesse caso, lança uma exceção.
As variáveis são, na verdade, armazenamentos, que podem ser passados funcionalmente, e as tabelas de armazenamento podem ser referências, criadas e destruídas à medida que os escopos são alterados.
Hashes e similares serão como em Lua e JavaScript.
Se eu vou criar uma linguagem compilada, vou criar um F # para Java, com recursos do tipo Haskell. É uma linguagem funcional pura, exceto que existe um recurso que combina Cotações e Comp Exprs para obter uma programação imperativa, escrevendo blocos semelhantes a pseudocódigo.
Tendo em mente que as únicas linguagens que conheço são PHP e javascript, e que realmente devo aprender mais algumas antes de criar uma linguagem:
Sintaxe: Pense cuidadosamente nos nomes das funções e na ordem dos argumentos (ou seja, seja menos confuso que o PHP).
Recursos:
Possui um conjunto de string
funções, que operam em variáveis como uma série de bytes, mas não entendem o texto, e um conjunto de text
funções, que entendem muitas codificações e podem operar no UTF-8 e em outras seqüências de vários bytes. (E possui verificações de integridade de codificação incorporadas ao idioma, com uma função como a text.isValidEncoding(text, encoding)
que informa se uma sequência de bytes está malformada e insegura para ser tratada como texto.
Acho que gosto da ideia de digitação estática forte, mas nunca a usei, por isso não posso dizer.
Antes de projetar uma linguagem de programação, eu encontraria uma boa resposta para a pergunta: por que precisamos de outra linguagem de programação? O Código Rosetta no momento da redação deste artigo lista 344 idiomas. Se nenhum deles atendesse às minhas necessidades, os detalhes específicos do motivo pelo qual eles não determinariam o ponto de partida (os idiomas mais próximos) e o que seria adicionado a ele.
Se eu ganhasse na loteria e, por algum motivo, não tivesse nada melhor para fazer, começaria com Liskell e a tornaria uma linguagem completa em oposição a um front-end do GHC, depois tornaria a FFI mais fácil (e automatizada) para que eu pudesse usar qualquer Biblioteca C / C ++.
Uma boa língua é uma linguagem que é:
É muito difícil transformar isso em uma lista de recursos, mas acho que a Programação Funcional, apesar de não parecer natural , está mais próxima disso do que a programação imperativa (especialmente para esconder os detalhes minuciosos)
No momento, o idioma mais próximo dessa lista é provavelmente Haskell, no entanto:
Para sua primeira pergunta, "como você faria isso" - resposta curta, eu não faria. Não tenho a teoria do analisador / compilador suficiente para fazer isso. Mas como programa há 25 anos, tenho algumas idéias e opiniões para compartilhar.
Primeiramente, eu tentaria criar uma abordagem OOP que permita criar modelos verdadeiramente conectados. O que quero dizer com isso é que os modelos são uma das coisas mais importantes em quase qualquer tipo de projeto de programação - é sempre muito trabalhoso e refatoração contínua para fazer o que é certo, e eu culpo isso por falta de conectividade real. Idiomas OO.
Permita-me demonstrar. Digamos que uma classe House tenha uma propriedade Door.
var door = house.Door;
Agora você tem uma variável local com uma referência à instância do Door.
Mas considere o que acabou de acontecer: você acabou de arrancar a porta da casa e agora está muito feliz passando a porta, e o resto do seu código ignora o fato de que essa porta está realmente conectada a uma casa.
Para mim, isso é fundamentalmente errado.
E sim, eu sei, isso é "facilmente" corrigido caso a caso - nesse caso, mantendo uma referência inversa de cada Porta da Casa à qual ela está atualmente conectada. É claro que isso abre seu modelo para erros, já que agora é seu dever manter com precisão duas referências reversas, para que você torne as propriedades House.Doors e Door.House privadas e adicione métodos como House.AddDoor (), House.RemoveDoor ( ), Door.SetHouse () etc., conecte tudo e teste-a para garantir que realmente funcione.
Isso não está começando a parecer muito trabalho para modelar um relacionamento tão direto? Muito código para manter? Muito código para refatorar à medida que o modelo evolui?
O problema é ponteiros. Toda linguagem OO que eu já vi inerentemente sofre com o fato de uma referência a objeto ser realmente um ponteiro, porque é isso que os computadores usam.
Ponteiros não são uma boa maneira de modelar o mundo real. Independentemente do mundo que você está tentando modelar, é quase garantido que qualquer relacionamento nesse mundo será de mão dupla. Os ponteiros apontam apenas em uma direção.
Eu gostaria de ver uma linguagem em que o modelo de dados fundamental seja um gráfico - em que todos os relacionamentos, por padrão, tenham duas extremidades. Isso certamente forneceria um ajuste muito mais natural para modelar o mundo real, que é realmente a única coisa para a qual precisamos de computadores. (isso e videogames.)
Não tenho idéia de como seria a sintaxe para uma linguagem como essa, ou se ela pode ser expressamente concebida usando texto. (Eu me perguntei se essa linguagem teria que ser gráfica, de alguma forma ...)
Eu também gostaria de ver todas as formas de estado acidental eliminadas.
Por exemplo, no desenvolvimento da Web, gastamos muito tempo moldando dados de bancos de dados, modelos de negócios, modelos de exibição para apresentação ... então alguns desses dados são apresentados em formulários, o que é realmente apenas outra transformação. .. e state volta das postagens de formulário e, em seguida, remodelamos esses dados e os projetamos de volta no modelo de exibição, por exemplo, ligadores de modelo de exibição e outros ... então projetamos do modelo de exibição de volta para o modelo de negócios model ... então usamos mapeadores objeto-relacionais (ou trabalho pesado) para transformar os dados do modelo de visualização e projetá-los em um banco de dados relacional ...
Isso está começando a parecer redundante? Em que ponto, durante toda essa loucura, realizamos alguma coisa útil? Por útil, quero dizer, algo tangível - algo que o usuário final possa entender e se importar. No final do dia, as horas que você passou construindo algo que os usuários podem entender são realmente as únicas horas bem gastas. Tudo o resto é efeitos colaterais.
Eu gostaria de uma linguagem altamente dinâmica. O ciclo de gravação / compilação / execução é um desperdício de tempo tedioso. Idealmente, o idioma deve apenas descobrir o que mudou e compilar / carregar de forma transparente, em segundo plano, conforme necessário.
Idealmente, você nem precisa pressionar "executar" - as coisas devem acontecer na tela, conforme você faz as alterações, refletindo imediatamente as alterações feitas. O problema com o ciclo de gravação / compilação / execução, ou mesmo o ciclo de gravação / execução mais direto, é que você está muito desconectado do que está fazendo - para se sentir conectado ao nosso trabalho, nós precisa de feedback imediato, resultados instantâneos. Qualquer espera é muito longa!
Novamente, nem sei se isso pode ser conseguido com um IDE tradicional ou se isso exigiria um tipo de interface totalmente novo.
Você poderá usar uma combinação de digitação fraca e forte, o que for mais adequado para o problema em que está trabalhando.
Estado em geral deve ser algo que o idioma gerencia totalmente para você. Por que você precisa confiar em um banco de dados para persistência? Idealmente, eu gostaria de poder simplesmente especificar o tempo de vida de qualquer variável no modelo: uma solicitação da Web, uma sessão, 24 horas, permanentemente.
Por que temos que escolher entre toda uma gama de soluções de armazenamento para diferentes mídias e condições de vida? - sem mencionar a transformação e modelagem dos dados para caber em cada mídia; cache do navegador, banco de dados, memória, disco, quem se importa! Dados são dados. Onde você armazena seus dados (e por quanto tempo) deve ser uma escolha simples, não uma batalha contra os deuses!
Bem, boa sorte com isso.
Provavelmente seria uma linguagem de paradigmas múltiplos, suportando o seguinte:
Por que esses? Orientado a objetos, porque é uma ótima maneira de organizar grandes programas, especialmente para organizar os dados. Estruturado porque você nem sempre quer / precisa disso (OOP), as pessoas devem ter escolha. Funcional porque facilita a depuração de programadores e torna os programas mais claros.
Eu usaria o modelo do Python com blocos recuados para marcar blocos de código. É muito agradável e agradável de ler.
Eu roubaria muitas idéias do Python, na verdade, porque o Python é uma linguagem muito agradável. Eu pegaria para declaração e copiaria seus mapas, lista e tuplas.
Agora, eu provavelmente não pegaria os conceitos dinâmicos do Python: por um lado, provavelmente seria explicitamente e estaticamente digitado. Eu acho que os programas ficam mais claros com isso. As variáveis provavelmente seriam objetos com métodos, então você poderia fazer algo como str.length()
obter o comprimento de uma string. Nas definições de função, você teria que especificar o tipo de retorno e os tipos dos argumentos (suportando também alguns tipos de tipos genéricos).
Vamos voltar a copiar do Python ;-). Eu amo que é maneira de ter argumentos de procedimento opcionais, então eu provavelmente teria isso. Python, no entanto, não suporta sobrecarga de procedimentos, eu gostaria disso.
Vamos dar uma olhada nas aulas, eu abandonaria a herança múltipla; fácil de abusar. Eu implementaria escopos privados e similares e provavelmente implementaria isso da maneira que é feita em C ++. Eu também teria classes abstratas e interfaces; Não acredito que o Python tenha isso.
Seria compatível com classes internas, na verdade, eu gostaria de uma linguagem orientada a objetos muito poderosa.
Provavelmente seria interpretado. É possível obtê-lo muito rápido usando uma boa compilação JIT (eu gostaria de uma linguagem rápida, embora a produtividade do programador fosse a primeira) e a compilação é ruim para a produtividade muitas vezes. Os idiomas interpretados também promovem a independência da plataforma, algo que importa cada vez mais a cada dia.
Teria embutido suporte Unicode; hoje em dia a internacionalização é muito importante.
Definitivamente seria lixo coletado. Porra, eu odeio fazer o gerenciamento de memória; também não é bom para produtividade.
Finalmente, teria uma boa biblioteca padrão.
Uau, acabei de perceber o quanto eu realmente amo Python.
Interpreted languages also promote platform independance
? Acho que existem mais intérpretes entre plataformas e compiladores (porcentagem), mas não consegui descobrir por que essa frase deveria ser verdadeira? Eu acho que não há nenhuma diferença entre eles, em relação às habilidades de plataforma cruzada.
Antes de tudo, eu comprava alguns livros sobre compiladores, alguns padrões e fazia um ou dois cursos em idiomas e compiladores. Contribuiria com PEP e visitaria as reuniões do comitê de padrões C ++. Eu contribuiria com patches para os compiladores que uso, espero que para recursos e bugs.
Depois, voltaria a olhar horrorizado para a lista apresentada agora, que é quais as direções que eu seguiria com um idioma se começasse agora:
Como esses pontos bastante amplos provavelmente mudariam rapidamente se eu começasse a implementar o idioma, acho que entrar em mais detalhes é desnecessário.
Se eu tivesse tempo, projetaria uma linguagem de programação localizável baseada no Scala, para que ele tivesse a maioria de seus recursos, exceto provavelmente para XML. Meu objetivo é criar um idioma que leia quase naturalmente em idiomas com uma estrutura diferente do inglês, como o árabe (minha língua materna). Estou pensando nos seguintes recursos:
#lang
diretiva de pré-processador , usada para informar o pré-processador da linguagem humana usada para programação. Por exemplo: #lang ar
permitiria o uso da palavra em فئة
vez de class
, em عرف
vez de def
e assim por diante. As palavras-chave específicas do idioma humano seriam definidas nos arquivos padrão do pré-processador.class MyClass is composed of {
para se tornar class MyClass {
e remover "como" def MyMethod(x: Int) as {
para se tornar def MyMethod(x: Int) {
. Em algumas línguas (humanas), isso tornaria o código muito mais fácil de entender, especialmente para os alunos.اعرض طول اسم محمد
, o que equivale a print(length(name(Mohammad)))
em inglês de programação. (Os parênteses são para maior clareza.)Acredito que essas mudanças mínimas no pré-processador e compilador tornariam a programação muito mais simples para quem não fala inglês.
print
) não faria mal.