A LINGUAGEM DE CEM ANOS
OriginalAbril de 2003
(Este ensaio é derivado de uma palestra principal no PyCon 2003.)
É difícil prever como será a vida daqui a cem anos. Há apenas algumas coisas que podemos dizer com certeza. Sabemos que todos vão dirigir carros voadores, que as leis de zoneamento serão relaxadas para permitir edifícios com centenas de andares de altura, que estará escuro a maior parte do tempo, e que as mulheres serão todas treinadas em artes marciais. Aqui quero dar um zoom em um detalhe desta imagem. Que tipo de linguagem de programação eles usarão para escrever o software que controla esses carros voadores?
Vale a pena pensar sobre isso não tanto porque realmente usaremos essas linguagens, mas porque, se tivermos sorte, usaremos linguagens no caminho de este ponto para aquele.
Acho que, como as espécies, as linguagens formarão árvores evolutivas, com becos sem saída ramificando-se por toda parte. Podemos ver isso acontecendo já. Cobol, apesar de sua popularidade em alguns momentos, não parece ter nenhum descendente intelectual. É um beco sem saída evolutivo - um linguagem neandertal.
Prevejo um destino semelhante para Java. As pessoas às vezes me enviam e-mails dizendo: "Como você pode dizer que Java não vai se tornar uma linguagem de sucesso? Já é uma linguagem de sucesso." E admito que é, se você medir o sucesso pelo espaço na prateleira ocupado por livros sobre ele (particularmente livros individuais sobre ele), ou por o número de graduandos que acreditam ter que aprendê-lo para conseguir um emprego. Quando digo que Java não vai se tornar uma linguagem de sucesso, quero dizer algo mais específico: que Java vai se tornar um beco sem saída evolutivo, como Cobol.
Isso é apenas um palpite. Posso estar errado. Meu ponto aqui não é desmerecer Java, mas levantar a questão de árvores evolutivas e fazer as pessoas perguntarem, onde na árvore está a linguagem X? A razão para fazer essa pergunta não é apenas para que nossos fantasmas possam dizer, daqui a cem anos, eu te avisei. É porque ficar perto de os ramos principais é uma heurística útil para encontrar linguagens que serão boas para programar agora.
Em qualquer momento, você provavelmente está mais feliz em os ramos principais de uma árvore evolutiva. Mesmo quando ainda havia muitos neandertais, deve ter sido péssimo ser um. O Cro-Magnons estariam constantemente vindo e te espancando e roubando sua comida.
A razão pela qual quero saber como serão as linguagens daqui a cem anos é para que eu saiba em qual ramo da árvore apostar agora.
A evolução das linguagens difere da evolução das espécies porque os ramos podem convergir. O ramo Fortran, por exemplo, parece estar se fundindo com os descendentes de Algol. Em teoria, isso é possível para espécies também, mas é improvável que tenha acontecido com algo maior que uma célula.
Convergência é mais provável para linguagens em parte porque o espaço de possibilidades é menor, e em parte porque mutações não são aleatórias. Os designers de linguagem incorporam deliberadamente ideias de outras linguagens.
É especialmente útil para os designers de linguagem pensar sobre para onde a evolução das linguagens de programação provavelmente vai levar, porque eles podem direcionar de acordo. Nesse caso, "permanecer em um ramo principal" se torna mais do que um forma de escolher uma boa linguagem. Torna-se uma heurística para tomar as decisões certas sobre design de linguagem.
Qualquer linguagem de programação pode ser dividida em duas partes: um conjunto de operadores fundamentais que desempenham o papel de axiomas, e o resto da linguagem, que em princípio poderia ser escrito em termos desses operadores fundamentais.
Acho que os operadores fundamentais são o fator mais importante em um a sobrevivência a longo prazo da linguagem. O resto você pode mudar. É como a regra de que ao comprar uma casa você deve considerar localização em primeiro lugar. Tudo o mais você pode consertar depois, mas você não pode consertar a localização.
Acho que é importante não apenas que os axiomas sejam bem escolhidos, mas que haja poucos deles. Os matemáticos sempre sentiram dessa forma sobre axiomas - quanto menos, melhor - e acho que eles estão certos.
No mínimo, tem que ser um exercício útil olhar de perto para o núcleo de uma linguagem para ver se há algum axioma que poderia ser eliminado. Descobri em minha longa carreira como um relaxado que a sujeira gera sujeira, e vi isso acontecer em software como bem como debaixo das camas e nos cantos dos quartos.
Tenho a sensação de que os ramos principais da árvore evolutiva passam pelas linguagens que têm os núcleos menores e mais limpos. Quanto mais de uma linguagem você pode escrever em si mesma, melhor.
Claro, estou fazendo uma grande suposição ao mesmo tempo em que pergunto o que serão as linguagens de programação daqui a cem anos. Ainda estaremos escrevendo programas daqui a cem anos? Não vamos apenas dizer aos computadores o que queremos que eles façam?
Não houve muito progresso nesse departamento até agora. Meu palpite é que daqui a cem anos as pessoas vão ainda dizer aos computadores o que fazer usando programas que reconheceríamos como tal. Pode haver tarefas que nós resolvemos agora escrevendo programas e que daqui a cem anos você não precisará escrever programas para resolver, mas acho que ainda haverá uma boa parte de programação do tipo que fazemos hoje.
Pode parecer presunçoso pensar que alguém pode prever o que qualquer tecnologia será daqui a cem anos. Mas lembre-se que já temos quase cinquenta anos de história atrás de nós. Olhar para frente cem anos é uma ideia compreensível quando consideramos o quão lentamente as linguagens evoluíram no últimos cinquenta.
As linguagens evoluem lentamente porque não são realmente tecnologias. Linguagens são notações. Um programa é uma descrição formal de o problema que você quer que um computador resolva para você. Então a taxa de evolução nas linguagens de programação é mais como a taxa de evolução na notação matemática do que, digamos, transporte ou comunicações. A notação matemática evolui, mas não com os saltos gigantes que você vê na tecnologia.
Seja qual for o material dos computadores daqui a cem anos, parece seguro prever que serão muito mais rápidos do que são agora. Se a Lei de Moore continuar a produzir, eles serão 74 quintilhões (73.786.976.294.838.206.464) vezes mais rápidos. Isso é meio difícil de imaginar. E de fato, a previsão mais provável no departamento de velocidade pode ser que a Lei de Moore pare de funcionar. Qualquer coisa que deve dobrar a cada dezoito meses parece provável que encontre algum tipo de limite fundamental eventualmente. Mas não tenho problemas em acreditar que os computadores serão muito mais rápidos. Mesmo que eles só acabem sendo um mísero milhão de vezes mais rápidos, isso deve mudar as regras do jogo para programação linguagens substancialmente. Entre outras coisas, haverá mais espaço para o que seria considerado linguagens lentas agora, ou seja, linguagens que não geram código muito eficiente.
E ainda assim, algumas aplicações ainda exigirão velocidade. Alguns dos problemas que queremos resolver com computadores são criados por computadores; por exemplo, o taxa na qual você tem que processar imagens de vídeo depende na taxa na qual outro computador pode gerá-los. E há outra classe de problemas que inerentemente têm uma capacidade ilimitada de absorver ciclos: renderização de imagens, criptografia, simulações.
Se algumas aplicações podem ser cada vez mais ineficientes enquanto outras continuam a exigir toda a velocidade que o hardware pode entregar, computadores mais rápidos significarão que as linguagens têm que cobrir uma gama cada vez maior de eficiências. Nós vimos isso acontecendo já. Implementações atuais de algumas novas linguagens populares são chocantemente desperdiçadoras pelo padrões das décadas anteriores.
Isso não é apenas algo que acontece com programação linguagens. É uma tendência histórica geral. À medida que as tecnologias melhoram, cada geração pode fazer coisas que a geração anterior teria considerado desperdício. Pessoas há trinta anos ficariam espantadas com a casualidade com que fazemos chamadas telefônicas de longa distância. Pessoas há cem anos ficariam ainda mais espantadas que um pacote um dia viajaria de Boston para Nova York via Memphis.
Já posso te dizer o que vai acontecer com todos aqueles extras ciclos que o hardware mais rápido vai nos dar no próximos cem anos. Quase todos eles serão desperdiçados.
Aprendi a programar quando o poder de computação era escasso. Lembro-me de remover todos os espaços dos meus programas Basic para que coubessem na memória de um TRS-80 de 4K. O pensamento de todo esse software estupidamente ineficiente queimando ciclos fazendo a mesma coisa repetidamente parece meio nojento para mim. Mas acho que minhas intuições aqui estão erradas. Eu sou como alguém que cresceu pobre e não suporta gastar dinheiro mesmo para algo importante, como ir ao médico.
Alguns tipos de desperdício realmente são nojentos. SUVs, por exemplo, seriam provavelmente nojentos mesmo que funcionassem com um combustível que nunca acabasse e não gerasse poluição. SUVs são nojentos porque são a solução para um problema nojento. (Como fazer minivans parecerem mais masculinas.) Mas nem todo desperdício é ruim. Agora que temos a infraestrutura para suportá-lo, contar os minutos de suas chamadas de longa distância começa a parecer mesquinho. Se você tem o recursos, é mais elegante pensar em todas as chamadas telefônicas como um tipo de coisa, não importa onde a outra pessoa esteja.
Há bom desperdício e mau desperdício. Estou interessado em bom desperdício - o tipo em que, gastando mais, podemos obter designs mais simples. Como vamos aproveitar as oportunidades para desperdiçar ciclos que obteremos de novos hardwares mais rápidos?
O desejo por velocidade é tão profundamente enraizado em nós, com nossos computadores minúsculos, que levará um esforço consciente para superá-lo. No design de linguagem, devemos estar conscientemente buscando situações em que podemos trocar eficiência por até mesmo o menor aumento na conveniência.
A maioria das estruturas de dados existe por causa da velocidade. Por exemplo, muitas linguagens hoje têm strings e listas. Semanticamente, strings são mais ou menos um subconjunto de listas em que os elementos são caracteres. Então por que você precisa de um tipo de dados separado? Você não precisa, realmente. Strings apenas existem por eficiência. Mas é chato sobrecarregar a semântica da linguagem com hacks para fazer os programas rodarem mais rápido. Ter strings em uma linguagem parece ser um caso de otimização prematura.
Se pensarmos no núcleo de uma linguagem como um conjunto de axiomas, certamente é nojento ter axiomas adicionais que não adicionam nenhum poder expressivo, simplesmente por causa da eficiência. Eficiência é importante, mas não acho que essa seja a maneira certa de obtê-la.
A maneira certa de resolver esse problema, acho, é separar o significado de um programa dos detalhes de implementação. Em vez de ter listas e strings, tenha apenas listas, com alguma forma de dar ao compilador conselhos de otimização que permitirão que ele organize as strings como bytes contíguos se necessário.
Como a velocidade não importa na maior parte de um programa, você não precisará normalmente se preocupar com esse tipo de microgerenciamento. Isso será cada vez mais verdade à medida que os computadores ficarem mais rápidos.
Dizer menos sobre implementação também deve tornar os programas mais flexíveis. As especificações mudam enquanto um programa está sendo escrito, e isso não é apenas inevitável, mas desejável.
A palavra "ensaio" vem do verbo francês "essayer", que significa "tentar". Um ensaio, no sentido original, é algo que você escreve para tentar descobrir algo. Isso acontece em software também. Acho que alguns dos melhores programas foram ensaios, no sentido de que os autores não sabiam quando começaram exatamente o que estavam tentando escrever.
Os hackers Lisp já sabem sobre o valor de ser flexível com estruturas de dados. Nós tendemos a escrever a primeira versão de um programa para que ele faça tudo com listas. Esses versões iniciais podem ser tão chocantemente ineficientes que leva um esforço consciente para não pensar no que eles estão fazendo, assim como, para mim pelo menos, comer um bife exige um esforço consciente para não pensar de onde ele veio.
O que os programadores daqui a cem anos estarão procurando, acima de tudo, é uma linguagem em que você pode juntar uma versão 1 incrivelmente ineficiente de um programa com o mínimo de esforço possível. Pelo menos, é assim que descreveríamos em termos atuais. O que eles dirão é que querem uma linguagem que seja fácil de programar.
Software ineficiente não é nojento. O que é nojento é uma linguagem que faz os programadores fazerem trabalho desnecessário. Perder tempo de programador é a verdadeira ineficiência, não perder tempo de máquina. Isso vai ficar cada vez mais claro à medida que os computadores ficarem mais rápidos.
Acho que se livrar das strings já é algo que nós poderíamos suportar pensar. Fizemos isso em Arc, e parece ser uma vitória; algumas operações que seriam difíceis de descrever como expressões regulares podem ser descritas facilmente como funções recursivas.
Até onde essa nivelação de estruturas de dados irá? Posso pensar em possibilidades que me chocam, mesmo com minha mente conscientemente ampliada. Vamos nos livrar de arrays, por exemplo? Afinal, eles são apenas um subconjunto de tabelas hash onde as chaves são vetores de inteiros. Vamos substituir as próprias tabelas hash por listas?
Existem perspectivas ainda mais chocantes do que isso. O Lisp que McCarthy descreveu em 1960, por exemplo, não tinha números. Logicamente, você não precisa ter uma noção separada de números, porque você pode representá-los como listas: o inteiro n poderia ser representado como uma lista de n elementos. Você pode fazer matemática dessa forma. É apenas incrivelmente ineficiente.
Ninguém realmente propôs implementar números como listas em prática. Na verdade, o artigo de McCarthy de 1960 não era, na época, destinado a ser implementado. Era um exercício teórico, uma tentativa de criar uma alternativa mais elegante à Máquina de Turing. Quando alguém, inesperadamente, pegou esse artigo e traduziu-o para um interpretador Lisp funcional, os números certamente não eram representados como listas; eles eram representados em binário, como em todas as outras linguagens.
Uma linguagem de programação poderia ir tão longe a ponto de se livrar dos números como um tipo de dados fundamental? Pergunto isso não tanto como uma pergunta séria mas como uma forma de brincar de "frango" com o futuro. É como o caso hipotético de uma força irresistível encontrando um objeto imóvel - aqui, uma implementação incrivelmente ineficiente encontrando recursos incrivelmente grandes. Não vejo por que não. O futuro é bem longo. Se houver algo que podemos fazer para diminuir o número de axiomas no núcleo linguagem, essa seria a aposta a ser feita à medida que t se aproxima do infinito. Se a ideia ainda parecer insuportável daqui a cem anos, talvez não seja daqui a mil.
Só para deixar claro, não estou propondo que todos os cálculos numéricos seriam realmente realizados usando listas. Estou propondo que a linguagem principal, antes de quaisquer notações adicionais sobre implementação, seja definida dessa forma. Na prática, qualquer programa que quisesse fazer alguma quantidade de matemática provavelmente representaria números em binário, mas isso seria uma otimização, não parte de a semântica da linguagem principal.
Outra forma de queimar ciclos é ter várias camadas de software entre o aplicativo e o hardware. Isso também é uma tendência que vemos acontecendo já: muitas linguagens recentes são compiladas para bytecode. Bill Woods certa vez me disse que, como regra geral, cada camada de interpretação custa um fator de 10 em velocidade. Esse custo extra compra flexibilidade.
A primeira versão do Arc foi um caso extremo desse tipo de lentidão de vários níveis, com benefícios correspondentes. Ele era um interpretador "metacircular" clássico escrito em cima do Common Lisp, com uma semelhança familiar definida com a função eval definida no artigo original de McCarthy sobre Lisp. A coisa toda tinha apenas algumas centenas de linhas de código, então era muito fácil de entender e mudar. O Common Lisp que usamos, CLisp, também roda em cima de um interpretador de bytecode. Então aqui tínhamos dois níveis de interpretação, um deles (o de cima) chocantemente ineficiente, e a linguagem era utilizável. Quase utilizável, admito, mas utilizável.
Escrever software como várias camadas é uma técnica poderosa mesmo dentro de aplicativos. A programação bottom-up significa escrever um programa como uma série de camadas, cada uma das quais serve como um linguagem para a de cima. Essa abordagem tende a produzir programas menores e mais flexíveis. Também é o melhor caminho para aquele santo graal, a reutilização. Uma linguagem é por definição reutilizável. Quanto mais de seu aplicativo você pode empurrar para baixo em uma linguagem para escrever esse tipo de aplicativo, mais seu software será reutilizável.
De alguma forma, a ideia de reutilização ficou anexada à programação orientada a objetos na década de 1980, e nenhuma quantidade de evidências em contrário parece ser capaz de tirá-la de lá. Mas embora algum software orientado a objetos seja reutilizável, o que o torna reutilizável é sua natureza bottom-up, não sua orientação a objetos. Considere bibliotecas: elas são reutilizáveis porque são linguagens, sejam escritas em um estilo orientado a objetos ou não.
Não prevejo o fim da programação orientada a objetos, por sinal. Embora eu não ache que ela tenha muito a oferecer a bons programadores, exceto em certos domínios especializados, ela é irresistível para grandes organizações. A programação orientada a objetos oferece uma forma sustentável de escrever código espaguete. Permite que você acumule programas como uma série de patches.
Grandes organizações sempre tendem a desenvolver software dessa forma, e espero que isso seja tão verdadeiro daqui a cem anos como é hoje.
Já que estamos falando sobre o futuro, é melhor falar sobre computação paralela, porque é aí que essa ideia parece viver. Ou seja, não importa quando você estiver falando, paralelo a computação parece ser algo que vai acontecer no futuro.
O futuro vai alcançá-lo algum dia? As pessoas têm falado sobre computação paralela como algo iminente por pelo menos 20 anos, e não afetou muito a prática de programação até agora. Ou não afetou? Já os designers de chips têm que pensar sobre isso, e também devem pessoas tentando escrever software de sistema em computadores multi-cpu.
A verdadeira questão é, até onde na escada da abstração vai o paralelismo? Daqui a cem anos, isso afetará até mesmo os programadores de aplicativos? Ou será algo que os escritores de compiladores pensam, mas que geralmente é invisível no código-fonte de aplicativos?
Uma coisa que parece provável é que a maioria das oportunidades para paralelismo serão desperdiçadas. Este é um caso especial do meu mais previsão geral de que a maior parte do poder de computação extra que estamos recebendo será desperdiçada. Espero que, como com a estupenda velocidade do hardware subjacente, o paralelismo será algo que está disponível se você solicitar explicitamente, mas normalmente não usado. Isso implica que o tipo de paralelismo que temos em cem anos não será, exceto em aplicações especiais, paralelismo massivo. Espero que para programadores comuns, será mais como poder bifurcar processos que acabam rodando em paralelo.
E isso será, como pedir implementações específicas de dados estruturas, algo que você faz bem no final da vida de um programa, quando você tenta otimizá-lo. As versões 1 normalmente ignorarão quaisquer vantagens a serem obtidas da computação paralela, apenas como ignorarão as vantagens a serem obtidas de representações específicas de dados.
Exceto em tipos especiais de aplicativos, o paralelismo não permeará os programas que serão escritos daqui a cem anos. Seria otimização prematura se o fizesse.
Quantas linguagens de programação haverá daqui a cem anos? Parece haver um número enorme de novas linguagens de programação ultimamente. Parte da razão é que hardware mais rápido permitiu que os programadores fizessem diferentes compensações entre velocidade e conveniência, dependendo do aplicativo. Se esta é uma tendência real, o hardware que nós teremos daqui a cem anos só deve aumentá-la.
E ainda assim, pode haver apenas algumas linguagens amplamente usadas em cem anos. Parte da razão pela qual digo isso é otimismo: parece que, se você fizesse um trabalho realmente bom, você poderia criar uma linguagem que fosse ideal para escrever um versão 1 lenta, e ainda assim com o conselho de otimização certo para o compilador, também geraria código muito rápido quando necessário. Então, como sou otimista, vou prever que, apesar da enorme lacuna que eles terão entre aceitável e máximo eficiência, os programadores daqui a cem anos terão linguagens que podem abranger a maior parte dela.
À medida que essa lacuna se amplia, os perfiladores se tornarão cada vez mais importantes. Pouca atenção é dada ao perfilamento agora. Muitas pessoas ainda parecem acreditar que a maneira de obter aplicativos rápidos é escrever compiladores que geram código rápido. À medida que a lacuna entre desempenho aceitável e máximo se amplia, ficará cada vez mais claro que a maneira de obter aplicativos rápidos é ter um bom guia de um para o outro.
Quando digo que pode haver apenas algumas linguagens, não estou incluindo "pequenas linguagens" específicas de domínio. Acho que essas linguagens embutidas são uma ótima ideia, e espero que elas proliferem. Mas espero que sejam escritas como peles finas o suficiente para que os usuários possam ver a linguagem de uso geral por baixo.
Quem vai projetar as linguagens do futuro? Uma das mais emocionantes tendências nos últimos dez anos tem sido a ascensão de código aberto linguagens como Perl, Python e Ruby. O design de linguagem está sendo assumido por hackers. Os resultados até agora são confusos, mas encorajadores. Existem algumas impressionantes ideias novas em Perl, por exemplo. Muitas são impressionantemente ruins, mas isso sempre é verdade para esforços ambiciosos. Em sua taxa atual de mutação, Deus sabe em que Perl pode evoluir em cem anos.
Não é verdade que aqueles que não podem fazer, ensinam (alguns dos melhores hackers que conheço são professores), mas é verdade que existem muitas coisas que aqueles que ensinam não podem fazer. Pesquisa impõe restrições de casta constrangedoras. Em qualquer acadêmico campo existem tópicos que são ok para trabalhar e outros que não são. Infelizmente, a distinção entre tópicos aceitáveis e tópicos proibidos geralmente se baseia em quão intelectual o trabalho soa quando descrito em artigos de pesquisa, em vez de quão importante é para obter bons resultados. O caso extremo é provavelmente a literatura; as pessoas que estudam literatura raramente dizem algo que seria de alguma utilidade para aqueles produzindo-o.
Embora a situação seja melhor nas ciências, a sobreposição entre o tipo de trabalho que você tem permissão para fazer e o tipo de trabalho que produz boas linguagens é assustadoramente pequeno. (Olin Shivers resmungou eloquentemente sobre isso.) Por exemplo, os tipos parecem ser uma fonte inesgotável de artigos de pesquisa, apesar do fato de que a tipagem estática parece impedir macros verdadeiras - sem as quais, na minha opinião, nenhuma linguagem vale a pena usar.
A tendência não é apenas para as linguagens serem desenvolvidas como projetos de código aberto em vez de "pesquisa", mas para linguagens sendo projetadas pelos programadores de aplicativos que precisam usá-los, em vez de por escritores de compiladores. Isso parece um bom tendência e espero que continue.
Ao contrário da física daqui a cem anos, que é quase necessariamente impossível de prever, acho que pode ser possível em princípio projetar uma linguagem agora que seria atraente para os usuários daqui a cem anos.
Uma forma de projetar uma linguagem é simplesmente escrever o programa que você gostaria de poder escrever, independentemente de se há um compilador que possa traduzi-lo ou hardware que possa executá-lo. Quando você faz isso, você pode assumir recursos ilimitados. Parece que deveríamos ser capazes de imaginar recursos ilimitados também hoje como daqui a cem anos.
Que programa alguém gostaria de escrever? O que dá menos trabalho. Exceto que não é bem assim: o que seria menos trabalho se suas ideias sobre programação não fossem influenciadas pelas linguagens que você está usando atualmente. Essa influência pode ser tão generalizada que leva um grande esforço para superá-la. Você pensaria que seria óbvio para criaturas tão preguiçosas como nós como expressar um programa com o mínimo de esforço. Na verdade, nossas ideias sobre o que é possível tendem a ser tão limitadas pela linguagem em que pensamos que formulações mais fáceis de programas parecem muito surpreendentes. Eles são algo que você tem que descobrir, não algo em que você naturalmente afunda.
Um truque útil aqui é usar o comprimento do programa como uma aproximação para quanto trabalho é para escrevê-lo. Não o comprimento em caracteres, é claro, mas o comprimento em elementos sintáticos distintos - basicamente, o tamanho da árvore de análise. Pode não ser bem verdade que o programa mais curto é o que dá menos trabalho para escrever, mas é próximo o suficiente para que você esteja melhor mirando no sólido alvo da brevidade do que no alvo nebuloso e próximo do menor trabalho. Então o algoritmo para design de linguagem se torna: olhe para um programa e pergunte, há alguma maneira de escrever isso que seja mais curta?
Na prática, escrever programas em uma linguagem imaginária de cem anos funciona em graus variados dependendo de quão perto você está do núcleo. Rotinas de classificação que você pode escrever agora. Mas seria difícil prever agora que tipos de bibliotecas podem ser necessárias em cem anos. Presumivelmente, muitas bibliotecas serão para domínios que nem existem ainda. Se SETI@home funcionar, por exemplo, nós precisaremos de bibliotecas para nos comunicar com alienígenas. A menos que, é claro, eles sejam suficientemente avançados para já se comunicarem em XML.
No outro extremo, acho que você pode projetar o linguagem principal hoje. Na verdade, alguns podem argumentar que ela já foi em grande parte projetada em 1958.
Se a linguagem de cem anos estivesse disponível hoje, nós quereríamos programar nela? Uma forma de responder a essa pergunta é olhar para trás. Se as linguagens de programação atuais estivessem disponíveis em 1960, alguém teria querido usá-las?
De certa forma, a resposta é não. As linguagens de hoje assumem infraestrutura que não existia em 1960. Por exemplo, uma linguagem em que a indentação é significativa, como Python, não funcionaria muito bem em terminais de impressora. Mas colocando esses problemas de lado - assumindo, por exemplo, que os programas eram todos apenas escritos em papel - os programadores da década de 1960 teriam gostado de escrever programas nas linguagens que usamos agora?
Acho que sim. Alguns dos menos imaginativos, que tinham artefatos de linguagens antigas embutidos em suas ideias de o que era um programa, pode ter tido problemas. (Como você pode manipular dados sem fazer aritmética de ponteiros? Como você pode implementar fluxogramas sem gotos?) Mas acho que os programadores mais inteligentes não teriam problemas em tirar o máximo proveito das linguagens atuais se eles as tivessem.
Se tivéssemos a linguagem de cem anos agora, ela pelo menos faria um ótimo pseudocódigo. E quanto a usá-la para escrever software? Como a linguagem de cem anos precisará gerar código rápido para alguns aplicativos, presumivelmente poderia gerar código eficiente o suficiente para rodar aceitavelmente bem em nosso hardware. Poderíamos ter que dar mais conselhos de otimização do que os usuários daqui a cem anos, mas ainda assim poderia ser uma vitória líquida.
Agora temos duas ideias que, se você combiná-las, sugerem interessantes possibilidades: (1) a linguagem de cem anos poderia, em princípio, ser projetada hoje, e (2) essa linguagem, se existisse, poderia ser boa para programar hoje. Quando você vê essas ideias dispostas assim, é difícil não pensar, por que não tentar escrever a linguagem de cem anos agora?
Quando você está trabalhando no design de linguagem, acho que é bom ter esse tipo de alvo e mantê-lo conscientemente em mente. Quando você aprende a dirigir, um dos princípios que eles te ensinam é alinhar o carro não alinhando o capô com as listras pintadas na estrada, mas mirando em algum ponto na distância. Mesmo se você só se importa com o que acontece nos próximos dez pés, este é o resposta certa. Eu acho que podemos e devemos fazer a mesma coisa com linguagens de programação.
Notas
Acredito que Lisp Machine Lisp foi a primeira linguagem a incorporar o princípio de que as declarações (exceto as de variáveis dinâmicas) eram apenas conselhos de otimização, e não mudaria o significado de um programa correto. Common Lisp parece ter sido o primeiro a declarar isso explicitamente.
Obrigado a Trevor Blackwell, Robert Morris e Dan Giffin por ler rascunhos disso, e a Guido van Rossum, Jeremy Hylton e o resto da equipe do Python por me convidar a falar no PyCon.