Loading...

A LINGUAGEM DOS CEM ANOS

Original

Abril de 2003

(Este 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 dizer com certeza. Sabemos que todos dirigirão carros voadores, que as leis de zoneamento serão relaxadas para permitir edifícios com centenas de andares de altura, que estará escuro na maior parte do tempo e que todas as mulheres serão treinadas em artes marciais. Aqui, quero ampliar 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 nisso não tanto porque realmente usaremos essas línguas, mas porque, se tivermos sorte, usaremos línguas no caminho deste ponto até aquele.

Eu acho que, assim como as espécies, as línguas formarão árvores evolutivas, com becos sem saída se ramificando por toda parte. Já podemos ver isso acontecendo. Cobol, apesar de toda sua popularidade ocasional, não parece ter descendentes intelectuais. É um beco sem saída evolutivo — uma língua 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? Ela já é uma linguagem de sucesso." E admito que é, se você medir o sucesso pelo espaço de prateleira ocupado por livros sobre ela (particularmente livros individuais sobre ela), ou pelo número de alunos de graduação que acreditam que precisam aprender 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 evolucionário, como Cobol.

Isto é 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 esta 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 é mais feliz nos galhos principais de uma árvore evolucionária. Mesmo quando ainda havia muitos neandertais, deve ter sido uma droga ser um. Os Cro-Magnons estariam constantemente vindo e batendo em você e roubando sua comida.

A razão pela qual quero saber como serão as línguas daqui a cem anos é para saber em qual galho da árvore apostar agora.

A evolução das línguas 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 também é possível para espécies, mas não é provável que tenha acontecido com algo maior do que uma célula.

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

É especialmente útil para designers de linguagem pensar sobre onde a evolução das linguagens de programação provavelmente levará, porque eles podem se orientar de acordo. Nesse caso, "ficar em um branch 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 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 restante da linguagem, que poderia, em princípio, ser escrito em termos desses operadores fundamentais.

Eu acho que os operadores fundamentais são o fator mais importante na sobrevivência de 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 antes de tudo. Todo o resto 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 se sentiram assim sobre axiomas-- quanto menos, melhor-- e acho que eles estão no caminho certo.

No mínimo, tem que ser um exercício útil olhar atentamente para o núcleo de uma linguagem para ver se há algum axioma que poderia ser eliminado. Descobri em minha longa carreira como um desleixado que lixo gera lixo, e já vi isso acontecer em softwares, bem como debaixo das camas e nos cantos dos quartos.

Tenho um palpite de que os principais ramos da árvore evolucionária passam pelas línguas que têm os núcleos menores e mais limpos. Quanto mais de uma língua 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. Será que estaremos escrevendo programas em cem anos? Não vamos simplesmente 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 ainda dirão aos computadores o que fazer usando programas que reconheceríamos como tal. Pode haver tarefas que resolvemos agora escrevendo programas e que em cem anos você não terá que 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 será qualquer tecnologia em cem anos. Mas lembre-se de que já temos quase cinquenta anos de história atrás de nós. Olhar para a frente cem anos é uma ideia compreensível quando consideramos o quão lentamente as línguas evoluíram nos últimos cinquenta.

As linguagens evoluem lentamente porque não são realmente tecnologias. As linguagens são notações. Um programa é uma descrição formal do problema que você quer que um computador resolva para você. Então 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 qual for a composição dos computadores em cem anos, parece seguro prever que eles 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 deva dobrar a cada dezoito meses parece provável que acabe encontrando 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 básicas para linguagens de programação. Entre outras coisas, haverá mais espaço para o que agora seriam consideradas linguagens lentas, ou seja, linguagens que não produzem código muito eficiente.

E ainda assim algumas aplicações ainda demandarão velocidade. Alguns dos problemas que queremos resolver com computadores são criados por computadores; por exemplo, a taxa na qual você tem que processar imagens de vídeo depende da taxa na qual outro computador pode gerá-las. 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 fornecer, computadores mais rápidos significarão que as linguagens terão que cobrir uma gama cada vez maior de eficiências. Já vimos isso acontecendo. As implementações atuais de algumas novas linguagens populares são chocantemente perdulárias pelos padrões das décadas anteriores.

Isso não é algo que acontece apenas 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 teria considerado desperdício. As pessoas de trinta anos atrás ficariam surpresas com a casualidade com que fazemos ligações telefônicas de longa distância. As pessoas de cem anos atrás ficariam ainda mais surpresas com o fato de um pacote um dia viajar de Boston para Nova York via Memphis.

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

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

Alguns tipos de desperdício são realmente nojentos. SUVs, por exemplo, seriam indiscutivelmente nojentos mesmo se 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 ligações de longa distância começa a parecer chato. Se você tem os recursos, é mais elegante pensar em todas as ligações 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 — o tipo em que, gastando mais, podemos obter designs mais simples. Como aproveitaremos as oportunidades de desperdiçar ciclos que obteremos com hardware novo e mais rápido?

O desejo por velocidade está tão profundamente enraizado em nós, com nossos computadores insignificantes, que será preciso um esforço consciente para superá-lo. No design de linguagem, deveríamos estar conscientemente buscando situações em que possamos negociar eficiência até mesmo pelo menor aumento em 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 dado separado? Você não precisa, na verdade. Strings existem apenas para eficiência. Mas é chato bagunçar a semântica da linguagem com hacks para fazer 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 é grosseiro ter axiomas adicionais que não acrescentam poder expressivo, simplesmente por uma questão de eficiência. Eficiência é importante, mas não acho que essa seja a maneira certa de obtê-la.

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

Como a velocidade não importa na maioria dos programas, você normalmente não precisará se preocupar com esse tipo de microgerenciamento. Isso será cada vez mais verdadeiro à medida que os computadores ficarem mais rápidos.

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

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. Essas versões iniciais podem ser tão chocantemente ineficientes que é preciso um esforço consciente para não pensar sobre o que 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 em cem anos estarão procurando, acima de tudo, é uma linguagem onde você possa juntar uma versão 1 inacreditavelmente ineficiente de um programa com o mínimo 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. Desperdiçar o tempo do programador é a verdadeira ineficiência, não desperdiçar o tempo da máquina. Isso ficará cada vez mais claro à medida que os computadores ficarem mais rápidos.

Acho que livrar-se de strings já é algo que poderíamos suportar pensar. Fizemos isso no Arc , e parece ser uma vitória; algumas operações que seriam estranhas de descrever como expressões regulares podem ser descritas facilmente como funções recursivas.

Até onde esse achatamento de estruturas de dados irá? Posso pensar em possibilidades que chocam até a mim, com minha mente conscienciosamente 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?

Há perspectivas ainda mais chocantes do que essa. 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. É simplesmente insuportavelmente ineficiente.

Ninguém realmente propôs implementar números como listas na prática. Na verdade, o artigo de McCarthy de 1960 não tinha, na época, a intenção de 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 o traduziu para um interpretador Lisp funcional, os números certamente não eram representados como listas; eles eram representados em binário, como em qualquer outra linguagem.

Uma linguagem de programação poderia ir tão longe a ponto de se livrar dos números como um tipo de dado fundamental? Eu pergunto isso não tanto como uma questão séria, mas como uma forma de brincar de galinha com 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 é bem longo. Se há algo que podemos fazer para diminuir o número de axiomas na linguagem principal, esse parece ser o lado a ser apostado conforme t se aproxima do infinito. Se a ideia ainda parece insuportável em cem anos, talvez não pareça em mil.

Só para deixar isso 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 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 principal.

Outra maneira de queimar ciclos é ter muitas camadas de software entre o aplicativo e o hardware. Essa também é uma tendência que já vemos acontecendo: muitas linguagens recentes são compiladas em código de bytes. Bill Woods me disse uma vez que, como regra geral, cada camada de interpretação custa um fator de 10 em velocidade. Esse custo extra compra flexibilidade para você.

A primeira versão do Arc foi um caso extremo desse tipo de lentidão multinível, com benefícios correspondentes. 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, 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. Mal utilizável, admito, mas utilizável.

Escrever software como múltiplas camadas é uma técnica poderosa mesmo dentro de aplicativos. Programação bottom-up significa escrever um programa como uma série de camadas, cada uma das quais serve como uma linguagem para a de cima. Essa abordagem tende a produzir programas menores e mais flexíveis. É também o melhor caminho para o Santo Graal, a reutilização. Uma linguagem é, por definição, reutilizável. Quanto mais do seu aplicativo você puder empurrar para baixo em uma linguagem para escrever esse tipo de aplicativo, mais do seu software será reutilizável.

De alguma forma, a ideia de reutilização foi anexada à 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 alguns softwares orientados a objetos sejam reutilizáveis, o que os torna reutilizáveis é sua bottom-upness, não sua orientação a objetos. Considere bibliotecas: elas são reutilizáveis porque são linguagem, sejam elas escritas em um estilo orientado a objetos ou não.

A propósito, não prevejo o fim da programação orientada a objetos. 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 maneira sustentável de escrever código espaguete. Ela permite que você agregue programas como uma série de patches.

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

Já que estamos falando sobre o futuro, é melhor falarmos sobre computação paralela, porque é onde essa ideia parece viver. Ou seja, não importa quando você esteja 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? Os projetistas de chips já precisam pensar sobre isso, e também as pessoas que tentam escrever software de sistemas em computadores multi-cpu.

A verdadeira questão é: até onde o paralelismo irá na escada da abstração? Em cem anos, ele afetará até mesmo os programadores de aplicativos? Ou será algo em que os escritores de compiladores pensam, mas que geralmente é invisível no código-fonte dos aplicativos?

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

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

Exceto em tipos especiais de aplicações, o paralelismo não vai permear os programas que serão escritos em cem anos. Seria uma otimização prematura se isso acontecesse.

Quantas linguagens de programação haverá em cem anos? Parece haver um grande número de novas linguagens de programação ultimamente. Parte do motivo é que hardware mais rápido permitiu que os programadores fizessem diferentes compensações entre velocidade e conveniência, dependendo da aplicação. Se essa for 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, você poderia fazer 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 produziria código muito rápido quando necessário. Então, como estou otimista, vou prever que, apesar da enorme lacuna que eles terão entre eficiência aceitável e máxima, os programadores em cem anos terão linguagens que podem abranger a maior parte dela.

À medida que essa lacuna aumenta, os profilers se tornarão cada vez mais importantes. Pouca atenção é dada à criação de perfil agora. Muitas pessoas ainda parecem acreditar que a maneira de obter aplicativos rápidos é escrever compiladores que gerem código rápido. À medida que a lacuna entre desempenho aceitável e máximo aumenta, 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 línguas, não estou incluindo "pequenas línguas" específicas de domínio. Acho que essas línguas incorporadas são uma ótima ideia, e espero que elas se proliferem. Mas espero que sejam escritas como peles 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 dos últimos dez anos tem sido a ascensão de linguagens de código aberto como Perl, Python e Ruby. O design de linguagens está sendo dominado por hackers. Os resultados até agora são confusos, mas encorajadores. Há algumas ideias surpreendentemente novas em Perl, por exemplo. Muitas são surpreendentemente ruins, mas isso é sempre verdade para esforços ambiciosos. Em sua taxa atual de mutação, Deus sabe no 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 há muitas coisas que aqueles que ensinam não podem fazer. A pesquisa impõe restrições de casta restritivas. Em qualquer campo acadêmico, há 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 proibidos geralmente é baseada em quão intelectual o trabalho soa quando descrito em artigos de pesquisa, em vez de quão importante ele é para obter bons resultados. O caso extremo é provavelmente a literatura; 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ê tem permissão para fazer e o tipo de trabalho que produz boas linguagens é assustadoramente pequena. (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 ser usada.

A tendência não é meramente para linguagens sendo desenvolvidas como projetos de código aberto em vez de "pesquisa", mas para linguagens sendo projetadas pelos programadores de aplicativos que precisam usá-las, em vez de escritores de compiladores. Isso parece uma boa 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 seja atraente para os usuários daqui a cem anos.

Uma maneira de projetar uma linguagem é simplesmente escrever o programa que você gostaria de ser capaz de 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, assim como em cem anos.

Que programa alguém gostaria de escrever? Qualquer coisa que dê menos trabalho. Exceto que não exatamente: qualquer coisa que daria menos trabalho se suas ideias sobre programação não fossem influenciadas pelas linguagens com as quais você está acostumado atualmente. Tal influência pode ser tão penetrante que é preciso 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 mínimo de esforço. Na verdade, nossas ideias sobre o que é possível tendem a ser tão limitadas por qualquer 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 aprofunda.

Um truque útil aqui é usar o comprimento do programa como uma aproximação de quanto trabalho é 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 alvo sólido da brevidade do que no alvo difuso 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 curto?

Na prática, escrever programas em uma linguagem imaginária de cem anos funcionará em graus variados, dependendo de quão perto você estiver 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 o SETI@home funcionar, por exemplo, precisaremos de bibliotecas para nos comunicarmos com alienígenas. A menos, é claro, que sejam suficientemente avançadas para já se comunicarem em XML.

No outro extremo, acho que você pode ser capaz de projetar a linguagem principal hoje. Na verdade, alguns podem argumentar que ela já foi projetada principalmente em 1958.

Se a linguagem centenária estivesse disponível hoje, gostaríamos de programar nela? Uma maneira de responder a essa pergunta é olhar para trás. Se as linguagens de programação atuais estivessem disponíveis em 1960, alguém gostaria de usá-las?

De certa forma, a resposta é não. As linguagens de hoje assumem uma 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 colocando esses problemas de lado — assumindo, por exemplo, que os programas eram todos escritos em papel — os programadores da década de 1960 teriam gostado de escrever programas nas linguagens que usamos agora?

Eu acho que sim. Alguns dos menos imaginativos, que tinham artefatos de linguagens antigas incorporados em suas ideias do que era um programa, podem ter tido problemas. (Como você pode manipular dados sem fazer aritmética de ponteiros? Como você pode implementar fluxogramas sem gotos?) Mas eu acho que os programadores mais inteligentes não teriam tido problemas em aproveitar ao máximo as linguagens atuais, se as tivessem.

Se tivéssemos a linguagem de cem anos agora, ela pelo menos daria um ótimo pseudocódigo. Que tal usá-la para escrever software? Como a linguagem de cem anos precisará gerar código rápido para alguns aplicativos, presumivelmente ela 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 em cem anos, mas ainda pode ser uma vitória líquida.

Agora temos duas ideias que, se você combiná-las, 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 dessa forma, é difícil não pensar, por que não tentar escrever a linguagem de cem anos agora?

Quando você está trabalhando em design de linguagem, acho que é bom ter um alvo assim 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 listras pintadas na estrada, mas mirando em algum ponto distante. Mesmo que tudo o que você se importe seja o que acontece nos próximos dez pés, esta é a resposta certa. 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 declarações (exceto aquelas de variáveis dinâmicas) eram meramente conselhos de otimização, e não mudariam o significado de um programa correto. Common Lisp parece ter sido a primeira a declarar isso explicitamente.

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