Loading...

A LINGUAGEM DE CEM ANOS

Original

Abril de 2003

(Esse ensaio é derivado de uma palestra principal na PyCon 2003.)

É difícil prever como será a vida em cem anos. Há apenas algumas coisas que podemos afirmar com certeza. Sabemos que todos irão dirigir carros voadores, que as leis de zoneamento serão relaxadas para permitir edifícios de centenas de andares, que estará escuro na maior parte do tempo e que todas as mulheres estarão treinadas em artes marciais. Aqui, quero me concentrar em um detalhe dessa imagem. Que tipo de linguagem de programação eles usarão para escrever o software que controla esses carros voadores?

Isso vale a pena pensar não tanto porque realmente usaremos essas linguagens, mas porque, se tivermos sorte, usaremos linguagens no caminho deste ponto até aquele.

Acho que, assim como as espécies, as linguagens formarão árvores evolutivas, com becos sem saída se ramificando por toda parte. Podemos ver isso acontecendo já. Cobol, por toda a sua popularidade ocasional, não parece ter nenhum descendente intelectual. É um beco sem saída evolutivo - uma linguagem Neandertal.

Prevejo um destino semelhante para Java. Às vezes, as pessoas me enviam e-mails dizendo: "Como você pode dizer que Java não se tornará uma linguagem de sucesso? Já é uma linguagem de sucesso." E eu admito que é, se você medir o sucesso pelo espaço nas prateleiras ocupado por livros sobre isso (particularmente livros individuais sobre isso), ou pelo número de alunos de graduação que acreditam que precisam aprendê-la para conseguir um emprego. Quando digo que Java não se tornará uma linguagem de sucesso, quero dizer algo mais específico: que Java 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 das á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, em cem anos, eu avisei. É porque ficar perto dos ramos principais é uma heurística útil para encontrar linguagens que serão boas para programar agora.

Em qualquer momento, você provavelmente está mais feliz nos ramos principais de uma árvore evolutiva. Mesmo quando ainda havia muitos Neandertais, deve ter sido horrível ser um. Os Cro-Magnons estariam constantemente vindo e te agredindo e roubando sua comida.

A razão pela qual quero saber como serão as linguagens em 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 do Fortran, por exemplo, parece estar se fundindo com os descendentes de Algol. Em teoria, isso também é possível para espécies, mas não é provável que tenha acontecido com algo maior que uma célula.

A convergência é mais provável para linguagens, em parte porque o espaço de possibilidades é menor, e em parte porque as mutações não são aleatórias. Os designers de linguagens incorporam deliberadamente ideias de outras linguagens.

É especialmente útil para os designers de linguagens pensar sobre onde a evolução das linguagens de programação provavelmente levará, porque eles podem direcionar-se de acordo. Nesse caso, "permanecer em um ramo principal" se torna mais do que uma maneira de escolher uma boa linguagem. Torna-se uma heurística para tomar as decisões certas sobre o design da 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 poderia, em princípio, ser escrito em termos desses operadores fundamentais.

Acho que os operadores fundamentais são o fator mais importante na sobrevivência a longo prazo de uma linguagem. O resto você pode mudar. É como a regra de que, ao comprar uma casa, você deve considerar a localização acima de tudo. Tudo o mais você pode consertar depois, mas 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 se sentiram assim em relação aos axiomas - quanto menos, melhor - e acho que eles estão certos.

No mínimo, deve ser um exercício útil olhar de perto para o núcleo de uma linguagem para ver se há axiomas que poderiam ser eliminados. Descobri, em minha longa carreira como desleixado, que a bagunça gera bagunça, e vi isso acontecer em software, assim como debaixo de camas e nos cantos dos quartos.

Tenho a intuiçã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ê puder escrever em si mesma, melhor.

Claro, estou fazendo uma grande suposição ao perguntar como serão as linguagens de programação em cem anos. Estaremos escrevendo programas em cem anos? Não estaremos apenas dizendo aos computadores o que queremos que eles façam?

Não houve muito progresso nesse departamento até agora. Meu palpite é que, em cem anos, as pessoas ainda dirão aos computadores o que fazer usando programas que reconheceríamos como tais. Pode haver tarefas que resolvemos agora escrevendo programas e que em cem anos você não precisará escrever programas para resolver, mas acho que ainda haverá uma boa quantidade de programação do tipo que fazemos hoje.

Pode parecer presunçoso pensar que alguém pode prever como qualquer tecnologia será em cem anos. Mas lembre-se de que já temos quase cinquenta anos de história atrás de nós. Olhar para frente em cem anos é uma ideia compreensível quando consideramos quão lentamente as linguagens evoluíram nos últimos cinquenta.

As linguagens evoluem lentamente porque não são realmente tecnologias. As linguagens são notação. Um programa é uma descrição formal do problema que você quer que um computador resolva para você. Portanto, a taxa de evolução nas linguagens de programação é mais parecida com 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 o que for que os computadores sejam feitos em cem anos, parece seguro prever que serão muito mais rápidos do que são agora. Se a Lei de Moore continuar a se manter, eles serão 74 quintilhões (73.786.976.294.838.206.464) de 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 deixará de funcionar. Qualquer coisa que supostamente deve dobrar a cada dezoito meses parece propensa a enfrentar 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 acabem sendo apenas um milhão de vezes mais rápidos, isso deve mudar substancialmente as regras do jogo para as linguagens de programação. Entre outras coisas, haverá mais espaço para o que agora seria considerado linguagens lentas, 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, a taxa na qual você precisa processar imagens de vídeo depende da taxa na qual outro computador pode gerá-las. E há outra classe de problemas que inherentemente 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 fornecer, computadores mais rápidos significarão que as linguagens terão que cobrir uma gama cada vez mais ampla de eficiências. Já vimos isso acontecendo. As implementações atuais de algumas linguagens novas populares são chocantemente desperdiciosas pelos padrões das décadas anteriores.

Isso não é apenas algo que acontece com linguagens de programação. É uma tendência histórica geral. À medida que as tecnologias melhoram, cada geração pode fazer coisas que a geração anterior consideraria desperdício. As pessoas de trinta anos atrás ficariam astonished com a forma casual como fazemos chamadas telefônicas de longa distância. As pessoas de cem anos atrás ficariam ainda mais surpresas que um pacote um dia viajaria de Boston a Nova York via Memphis.

Já posso te dizer o que vai acontecer com todos aqueles ciclos extras que o hardware mais rápido nos dará nos próximos cem anos. Quase todos eles serão desperdiçados.

Aprendi a programar quando o poder computacional era escasso. Lembro-me de tirar todos os espaços dos meus programas em Basic para que coubessem na memória de um TRS-80 de 4K. O pensamento de todo esse software estupendamente ineficiente queimando ciclos fazendo a mesma coisa repetidamente parece meio nojento para mim. Mas acho que minhas intuições aqui estão erradas. Sou como alguém que cresceu pobre e não consegue suportar gastar dinheiro, mesmo para algo importante, como ir ao médico.

Alguns tipos de desperdício realmente são nojentos. SUVs, por exemplo, seriam discutíveis mesmo se funcionassem com um combustível que nunca acabasse e não gerassem 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 os recursos, é mais elegante pensar em todas as chamadas telefônicas como um tipo de coisa, não importa onde a outra pessoa esteja.

Há desperdício bom e desperdício ruim. Estou interessado em desperdício bom - aquele em que, ao gastar mais, podemos obter designs mais simples. Como aproveitaremos as oportunidades de desperdiçar ciclos que teremos com o novo hardware mais rápido?

O desejo por velocidade está tão profundamente enraizado em nós, com nossos computadores insignificantes, que será necessário um esforço consciente para superá-lo. No design de linguagens, devemos estar buscando conscientemente situações em que possamos trocar eficiência por até mesmo o menor aumento de conveniência.

A maioria das estruturas de dados existe por causa da velocidade. Por exemplo, muitas linguagens hoje têm tanto strings quanto listas. Semanticamente, strings são mais ou menos um subconjunto de listas nas quais os elementos são caracteres. Então, por que você precisa de um tipo de dado separado? Você não precisa, realmente. Strings existem apenas por eficiência. Mas é ridículo poluir a semântica da linguagem com gambiarras 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 poder expressivo, simplesmente por uma questão de eficiência. A eficiência é importante, mas não acho que essa seja a maneira certa de obtê-la.

A maneira certa de resolver esse problema, eu acho, é separar o significado de um programa dos detalhes de implementação. Em vez de ter tanto listas quanto strings, tenha apenas listas, com alguma forma de dar ao compilador conselhos de otimização que permitirão que ele organize strings como bytes contíguos, se necessário.

Como a velocidade não importa na maior parte de um programa, você normalmente não precisará se preocupar com esse tipo de micromanagement. Isso será cada vez mais verdade à medida que os computadores se tornarem mais rápidos.

Dizer menos sobre a 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 no software também. Acho que alguns dos melhores programas foram ensaios, no sentido de que os autores não sabiam exatamente o que estavam tentando escrever quando começaram.

Os hackers de Lisp já conhecem o valor de ser flexível com estruturas de dados. Tendemos a escrever a primeira versão de um programa de modo que ele faça tudo com listas. Essas versões iniciais podem ser tão chocantemente ineficientes que é necessário um esforço consciente para não pensar no que estão fazendo, assim como, para mim pelo menos, comer um bife requer um esforço consciente para não pensar de onde ele veio.

O que os programadores em cem anos estarão procurando, acima de tudo, é uma linguagem onde você possa juntar uma versão 1 incrivelmente ineficiente de um programa com o menor esforço possível. Pelo menos, é assim que descreveríamos isso 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. Desperdiçar o tempo do programador é a verdadeira ineficiência, não desperdiçar o tempo da máquina. Isso se tornará cada vez mais claro à medida que os computadores se tornarem mais rápidos.

Acho que nos livrar de strings já é algo que poderíamos considerar. 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 achatamento de estruturas de dados irá? Posso pensar em possibilidades que até me chocam, 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 tabelas hash por listas?

Há 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 pode representá-los como listas: o inteiro n poderia ser representado como uma lista de n elementos. Você pode fazer matemática dessa maneira. É apenas insuportavelmente ineficiente.

Ninguém realmente propôs implementar números como listas na prática. De fato, o artigo de McCarthy de 1960 não foi, na época, destinado a ser implementado. Foi 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 o traduziu em um interpretador Lisp funcional, os números certamente não foram representados como listas; foram representados em binário, como em qualquer outra linguagem.

Uma linguagem de programação poderia ir tão longe a ponto de se livrar de números como um tipo de dado fundamental? Pergunto isso não tanto como uma pergunta séria, mas como uma forma de desafiar o futuro. É como o caso hipotético de uma força irresistível encontrando um objeto imóvel - aqui, uma implementação inimaginavelmente ineficiente encontrando recursos inimaginavelmente grandes. Não vejo por que não. O futuro é bastante longo. Se há algo que podemos fazer para diminuir o número de axiomas na linguagem central, isso pareceria ser o lado a apostar à medida que t se aproxima do infinito. Se a ideia ainda parecer insuportável em cem anos, talvez não pareça em mil.

Só para deixar claro, não estou propondo que todos os cálculos numéricos sejam realmente realizados usando listas. Estou propondo que a linguagem central, antes de quaisquer anotações adicionais sobre implementação, seja definida dessa maneira. Na prática, qualquer programa que quisesse fazer qualquer quantidade de matemática provavelmente representaria números em binário, mas isso seria uma otimização, não parte da semântica da linguagem central.

Outra maneira de queimar ciclos é ter muitas camadas de software entre a aplicação e o hardware. Isso também é uma tendência que já vemos acontecendo: muitas linguagens recentes são compiladas em bytecode. Bill Woods uma vez me disse que, como regra geral, cada camada de interpretação custa um fator de 10 em velocidade. Esse custo extra lhe dá flexibilidade.

A primeira versão do Arc foi um caso extremo desse tipo de lentidão em múltiplos níveis, com benefícios correspondentes. Era um clássico interpretador "metacircular" escrito sobre o Common Lisp, com uma clara semelhança familiar à função eval definida no artigo original de Lisp de McCarthy. O conjunto todo 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, por sua vez, roda sobre um interpretador de bytecode. Assim, aqui tínhamos dois níveis de interpretação, um deles (o superior) chocantemente ineficiente, e a linguagem era utilizável. Quase utilizável, admito, mas utilizável.

Escrever software como múltiplas camadas é uma técnica poderosa mesmo dentro de aplicações. Programação de baixo para cima significa escrever um programa como uma série de camadas, cada uma das quais serve como uma linguagem para a que está acima. 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 da sua aplicação você puder empurrar para baixo em uma linguagem para escrever esse tipo de aplicação, mais do seu software será reutilizável.

De alguma forma, a ideia de reutilização foi ligada à programação orientada a objetos na década de 1980, e nenhuma quantidade de evidência em contrário parece ser capaz de libertá-la. Mas, embora algum software orientado a objetos seja reutilizável, o que o torna reutilizável é sua natureza de baixo para cima, não sua orientação a objetos. Considere bibliotecas: elas são reutilizáveis porque são linguagem, independentemente de serem escritas em um estilo orientado a objetos ou não.

Não prevejo o fim da programação orientada a objetos, a propósito. Embora não ache que tenha muito a oferecer a bons programadores, exceto em certos domínios especializados, é irresistível para grandes organizações. A programação orientada a objetos oferece uma maneira sustentável de escrever código espaguete. Permite que você acumule programas como uma série de correções.

Grandes organizações sempre tendem a desenvolver software dessa maneira, e espero que isso seja tão verdadeiro em cem anos quanto é hoje.

Enquanto estamos falando sobre o futuro, é melhor falarmos sobre computação paralela, porque é aí que essa ideia parece viver. Ou seja, não importa quando você está falando, a computação paralela parece ser algo que vai acontecer no futuro.

O futuro algum dia alcançará isso? As pessoas têm falado sobre computação paralela como algo iminente por pelo menos 20 anos, e isso 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 nisso, e assim devem fazer as pessoas que tentam escrever software de sistema em computadores multi-CPU.

A verdadeira questão é: até onde a paralelização irá na escada da abstração? Em cem anos, isso afetará até mesmo programadores de aplicações? Ou será algo que os escritores de compiladores pensam, mas que geralmente é invisível no código-fonte das aplicações?

Uma coisa que parece provável é que a maioria das oportunidades para paralelismo será desperdiçada. Este é um caso especial da minha previsão mais geral de que a maior parte do poder computacional extra que nos é dado será desperdiçado. Espero que, assim como a velocidade estonteante do hardware subjacente, o paralelismo será algo que estará disponível se você pedir explicitamente, mas que normalmente não será usado. Isso implica que o tipo de paralelismo que teremos em cem anos não será, exceto em aplicações especiais, paralelismo massivo. Espero que, para programadores comuns, será mais como ser capaz de criar processos que acabam rodando em paralelo.

E isso será, como pedir implementações específicas de estruturas de dados, algo que você fará relativamente tarde na vida de um programa, quando tentar otimizá-lo. Versões 1 normalmente ignorarão quaisquer vantagens a serem obtidas com a computação paralela, assim como ignorarão vantagens a serem obtidas com representações específicas de dados.

Exceto em tipos especiais de aplicações, o paralelismo não permeia os programas que serão escritos em cem anos. Seria otimização prematura se o fizesse.

Quantas linguagens de programação haverá em 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 programadores fizessem diferentes trocas entre velocidade e conveniência, dependendo da aplicação. Se essa é uma tendência real, o hardware que teremos em cem anos deve apenas aumentá-la.

E ainda assim, pode haver apenas algumas linguagens amplamente utilizadas em cem anos. Parte da razão pela qual digo isso é otimismo: parece que, se você fizesse um trabalho realmente bom, poderia criar uma linguagem que fosse ideal para escrever uma 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. Portanto, como sou otimista, vou prever que, apesar da enorme lacuna que terão entre eficiência aceitável e máxima, os programadores em cem anos terão linguagens que podem abranger a maior parte disso.

À medida que essa lacuna se amplia, os profilers se tornarão cada vez mais importantes. Pouca atenção é dada à profilagem agora. Muitas pessoas ainda parecem acreditar que a maneira de obter aplicações rápidas é escrever compiladores que gerem 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 aplicações rápidas é 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 tais linguagens embutidas são uma ótima ideia e espero que proliferem. Mas espero que sejam escritas como camadas finas o suficiente para que os usuários possam ver a linguagem de propósito geral por baixo.

Quem projetará as linguagens do futuro? Uma das tendências mais empolgantes nos últimos dez anos foi a ascensão de linguagens de código aberto como Perl, Python e Ruby. O design de linguagens está sendo assumido por hackers. Os resultados até agora são bagunçados, mas encorajadores. Há algumas ideias surpreendentemente novas em Perl, por exemplo. Muitas são surpreendentemente ruins, mas isso sempre é verdade em esforços ambiciosos. Na taxa atual de mutação, Deus sabe no que Perl pode evoluir em cem anos.

Não é verdade que aqueles que não conseguem fazer, ensinam (alguns dos melhores hackers que conheço são professores), mas é verdade que há muitas coisas que aqueles que ensinam não conseguem fazer. A pesquisa impõe restrições de casta limitantes. Em qualquer campo acadêmico, há tópicos que são aceitáveis para trabalhar e outros que não são. Infelizmente, a distinção entre tópicos aceitáveis e proibidos geralmente é baseada 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 que a produzem.

Embora a situação seja melhor nas ciências, a sobreposição entre o tipo de trabalho que você está autorizado a fazer e o tipo de trabalho que gera boas linguagens é alarmantemente pequena. (Olin Shivers se queixou eloquentemente sobre isso.) Por exemplo, tipos parecem ser uma fonte inesgotável de artigos de pesquisa, apesar do fato de que a tipagem estática parece excluir verdadeiros macros - sem os quais, na minha opinião, nenhuma linguagem vale a pena usar.

A tendência não é apenas em direção a linguagens sendo desenvolvidas como projetos de código aberto em vez de "pesquisa", mas em direção a linguagens sendo projetadas pelos programadores de aplicação que precisam usá-las, em vez de pelos escritores de compiladores. Isso parece uma boa tendência e espero que continue.

Diferente da física em cem anos, que é quase necessariamente impossível de prever, acho que pode ser possível, em princípio, projetar uma linguagem agora que atraia usuários em cem anos.

Uma maneira de projetar uma linguagem é simplesmente escrever o programa que você gostaria de poder escrever, independentemente de haver um compilador que possa traduzi-lo ou hardware que possa executá-lo. Quando você faz isso, pode assumir recursos ilimitados. Parece que deveríamos ser capazes de imaginar recursos ilimitados tão bem hoje quanto em cem anos.

Que programa alguém gostaria de escrever? O que for menos trabalho. Exceto que não exatamente: o que seria menos trabalho se suas ideias sobre programação não fossem já influenciadas pelas linguagens que você está atualmente acostumado. Tal influência pode ser tão abrangente que leva um grande esforço para superá-la. Você pensaria que seria óbvio para criaturas tão preguiçosas quanto nós como expressar um programa com o menor 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. Elas são algo que você tem que descobrir, não algo em que você naturalmente se afunda.

Um truque útil aqui é usar o comprimento do programa como uma aproximação de quanto trabalho é escrever. 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 exatamente verdade que o programa mais curto é o que dá menos trabalho para escrever, mas é próximo o suficiente que você está melhor mirando no alvo sólido da brevidade do que no alvo difuso e próximo do menor trabalho. Então, o algoritmo para o design de linguagem se torna: olhe para um programa e pergunte-se, há alguma maneira de escrever isso que seja mais curta?

Na prática, escrever programas em uma linguagem imaginária de cem anos funcionará em graus variados, dependendo de quão próximo você está do núcleo. Rotinas de ordenaçã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 ainda nem existem. Se o SETI@home funcionar, por exemplo, precisaremos de bibliotecas para nos comunicarmos com alienígenas. A menos, é claro, que eles sejam suficientemente avançados para já se comunicarem em XML.

No outro extremo, acho que você pode ser capaz de projetar a linguagem central hoje. De fato, alguns poderiam argumentar que ela já foi em sua maior parte projetada em 1958.

Se a linguagem de cem anos estivesse disponível hoje, nós quereríamos programar nela? Uma maneira de responder a essa pergunta é olhar para trás. Se as linguagens de programação atuais tivessem estado disponíveis em 1960, alguém teria querido usá-las?

De algumas maneiras, a resposta é não. As linguagens hoje assumem infraestrutura que não existia em 1960. Por exemplo, uma linguagem na qual a indentação é significativa, como Python, não funcionaria muito bem em terminais de impressora. Mas deixando de lado tais problemas - assumindo, por exemplo, que os programas fossem 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 incorporados em suas ideias sobre o que era um programa, poderiam 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 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 algumas aplicações, presumivelmente poderia gerar código eficiente o suficiente para rodar de forma aceitável em nosso hardware. Poderíamos ter que dar mais conselhos de otimização do que os usuários em cem anos, mas ainda assim poderia ser uma vitória líquida.

Agora temos duas ideias que, se você as combinar, sugerem possibilidades interessantes: (1) a linguagem de cem anos poderia, em princípio, ser projetada hoje, e (2) tal 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 tal alvo e mantê-lo conscientemente em mente. Quando você aprende a dirigir, um dos princípios que eles ensinam é alinhar o carro não alinhando o capô com as faixas pintadas na estrada, mas mirando em algum ponto à distância. Mesmo que tudo o que você se preocupe seja o que acontece nos próximos três metros, essa é a resposta certa. Acho que podemos e devemos fazer a mesma coisa com as linguagens de programação.

Notas

Acredito que o Lisp Machine Lisp foi a primeira linguagem a incorporar o princípio de que declarações (exceto as de variáveis dinâmicas) eram meramente conselhos de otimização e não mudariam o significado de um programa correto. O Common Lisp parece ter sido o primeiro a afirmar isso explicitamente.

Agradecimentos a Trevor Blackwell, Robert Morris e Dan Giffin por lerem rascunhos disso, e a Guido van Rossum, Jeremy Hylton e o resto da equipe do Python por me convidarem para falar na PyCon.