Loading...

O IDIOMA DO SÉCULO

Original

Abril de 2003

(Este ensaio é derivado de um discurso principal na PyCon 2003.)

É difícil prever como será a vida daqui a cem anos. Há apenas algumas coisas que podemos afirmar 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, que ficará escuro a maior parte do tempo e que todas as mulheres serão treinadas nas 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?

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

Acho que, como as espécies, as linguagens formarão árvores evolutivas, com becos sem saída se ramificando por toda parte. Já podemos ver isso acontecendo. O Cobol, por toda a sua popularidade em algum momento, não parece ter nenhum descendente intelectual. É um beco sem saída evolutivo - uma linguagem neandertal.

Eu prevejo um destino semelhante para o Java. As pessoas às vezes me enviam e-mails dizendo: "Como você pode dizer que o Java não vai se tornar uma linguagem bem-sucedida? Já é uma linguagem bem-sucedida". E eu admito que é, se você medir o sucesso pelo espaço nas estantes ocupado por livros sobre ele (particularmente livros individuais sobre ele) ou pelo número de estudantes universitários que acreditam que precisam aprendê-lo para conseguir um emprego. Quando digo que o Java não vai se tornar uma linguagem bem-sucedida, quero dizer algo mais específico: que o Java vai se revelar um beco sem saída evolutivo, como o Cobol.

Isso é apenas um palpite. Posso estar errado. Meu ponto aqui não é desacreditar o Java, mas levantar a questão das árvores evolutivas e fazer as pessoas se 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 disse que isso ia acontecer". É porque ficar perto dos ramos principais é uma heurística útil para encontrar linguagens que serão boas de programar agora.

Em qualquer momento, você provavelmente ficará mais feliz nos ramos principais de uma árvore evolutiva. Mesmo quando ainda havia muitos neandertais, deve ter sido uma droga ser um deles. Os Cro-Magnons provavelmente estariam constantemente vindo e batendo em você, roubando sua comida.

A razão pela qual quero saber como serão as linguagens daqui a cem anos é para saber 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 do Algol. Em teoria, isso é possível para as espécies também, mas é improvável que tenha acontecido com algo maior do que uma célula.

A convergência é mais provável para as 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 deliberadamente incorporam ideias de outras linguagens.

É especialmente útil para os designers de linguagens pensar sobre para onde a evolução das linguagens de programação provavelmente levará, porque eles podem se orientar de acordo. Nesse caso, "ficar 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 restante 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 para a 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 importante não apenas que os axiomas sejam bem escolhidos, mas que haja poucos deles. Os matemáticos sempre sentiram isso sobre os axiomas - quanto menos, melhor - e acho que eles estão certos.

No mínimo, tem que ser um exercício útil olhar de perto o núcleo de uma linguagem para ver se há algum axioma que poderia ser eliminado. Encontrei em minha longa carreira como um vagabundo que a sujeira gera sujeira, e vi isso acontecer no software bem como debaixo de camas e nos cantos dos quartos.

Tenho a sensação de que os principais ramos da árvore evolutiva passam pelas linguagens que têm o núcleo mais pequeno e mais limpo. Quanto mais de uma linguagem você puder escrever nela mesma, melhor.

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

Não houve muito progresso nessa área 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 tais. Pode haver tarefas que resolvemos agora escrevendo programas e que em cem anos 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 o que qualquer tecnologia parecerá em cem anos. Mas lembre-se de que já temos quase cinquenta anos de história atrás de nós. Olhar para frente por cem anos é uma ideia apreensível quando consideramos o quão lentamente as linguagens evoluíram nos últimos cinquenta.

As linguagens evoluem lentamente porque elas 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ê. 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 grandes saltos que você vê na tecnologia.

Quaisquer que sejam os computadores feitos 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 funcionar, 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 na departamento de velocidade pode ser que a Lei de Moore pare de funcionar. Qualquer coisa que supostamente dobre a cada dezoito meses parece provável que encontre algum tipo de limite fundamental eventualmente. Mas não tenho dificuldade em acreditar que os computadores serão muito mais rápidos. Mesmo que acabem sendo apenas um mísero milhão de vezes mais rápidos, isso deve mudar as regras básicas para linguagens de programação substancialmente. Entre outras coisas, haverá mais espaço para o que agora seria considerado linguagens lentas, significando linguagens que não produzem 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ê tem que processar imagens de vídeo depende da 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 puderem 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 mais ampla de eficiências. Vimos isso acontecendo já. As implementações atuais de algumas novas linguagens populares são surpreendentemente desperdiçadoras pelos padrões de 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 teria considerado desperdiçadoras. As pessoas de trinta anos atrás ficariam espantadas com a forma como fazemos ligações de longa distância. As pessoas de cem anos atrás ficariam ainda mais espantadas que um pacote viajaria de Boston para Nova York via Memphis.

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

Aprendi a programar quando o poder computacional era escasso. Posso me lembrar de tirar todos os espaços dos meus programas em Basic para que eles coubessem na memória de um TRS-80 de 4K. O pensamento de todo esse software incrivelmente 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 consegue gastar dinheiro mesmo para algo importante, como ir ao médico.

Alguns tipos de desperdício realmente são nojosos. SUVs, por exemplo, seriam argumentavelmente nojentos mesmo se rodassem 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 mesquinho. Se você tem os recursos, é mais elegante pensar em todas as ligações telefônicas como um único tipo de coisa, não importa onde a outra pessoa esteja.

Existe um bom desperdício e um mau desperdício. Estou interessado no bom desperdício - o tipo em que, gastando mais, podemos obter designs mais simples. Como aproveitaremos as oportunidades de desperdiçar ciclos que obteremos de hardware mais rápido?

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

A maioria das estruturas de dados existe por causa da velocidade. Por exemplo, muitas linguagens hoje em dia têm tanto strings quanto 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 existem apenas por eficiência. Mas é lamentável poluir a semântica da linguagem com truques para fazer os programas serem executados 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. A 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 tanto listas quanto strings, ter 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 vai precisar se preocupar com esse tipo de microgerenciamento. Isso será cada vez mais verdade à medida que os computadores ficarem 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 também acontece em software. 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 para que ele faça tudo com listas. Essas versões iniciais podem ser tão chocantemente ineficientes que leva um esforço consciente não pensar no que elas estão fazendo, assim como, pelo menos para mim, comer um bife requer um esforço consciente para não pensar de onde ele veio.

O que os programadores daqui a cem anos estarão procurando, na maioria das vezes, é uma linguagem em que 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 fácil de programar.

Software ineficiente não é nojento. O que é nojento é uma linguagem que faz os programadores fazerem um 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.

Eu acho que nos livrar de strings já é algo sobre o qual poderíamos pensar. Fizemos isso em Arc, e parece ser um ganho; algumas operações que seriam desajeitadas de descrever como expressões regulares podem ser descritas facilmente como funções recursivas.

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

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 maneira. É apenas 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 se destinava, na época, a ser implementado. Era um exercício teórico, uma tentativa de criar uma alternativa mais elegante à Máquina de Turing. Quando alguém fez, inesperadamente, este artigo e o traduziu em um interpretador Lisp funcional, os números certamente não foram representados como listas; eles foram representados em binário, como em qualquer outra linguagem.

Será que uma linguagem de programação pode chegar ao ponto de se livrar dos números como um tipo de dados fundamental? Eu faço essa pergunta não tanto como uma questão séria, mas como uma maneira de jogar "chicken" com o futuro. É como o caso hipotético de uma força irresistível encontrando um objeto imóvel - aqui, uma implementação imensamente ineficiente encontrando recursos imensamente 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 principal, essa parece ser a aposta à medida que t se aproxima do infinito. Se a ideia ainda parecer insuportável em cem anos, talvez não o seja em mil.

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

Outra maneira de gastar 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 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 compra flexibilidade.

A primeira versão do Arc foi um caso extremo desse tipo de lentidão multinível, com benefícios correspondentes. Era um clássico interpretador "metacircular" escrito em cima do Common Lisp, com um parentesco definitivo com a função eval definida no artigo original de Lisp de McCarthy. Todo o sistema tinha apenas algumas centenas de linhas de código, então era muito fácil de entender e modificar. O Common Lisp que usamos, o CLisp, por sua vez, é executado em cima de um interpretador de bytecode. Então aqui tínhamos dois níveis de interpretação, um deles (o superior) 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. A programação bottom-up significa escrever um programa como uma série de camadas, cada uma das quais serve como uma linguagem para a camada acima. Essa abordagem tende a produzir programas menores e mais flexíveis. Também é a melhor rota para aquele santo graal, a reutilização. Uma linguagem é, por definição, reutilizável. Quanto mais de seu aplicativo você puder empurrar para baixo em uma linguagem para escrever esse tipo de aplicativo, mais de seu software será reutilizável.

De alguma forma, a ideia de reutilização ficou associada à programação orientada a objetos na década de 1980, e nenhuma quantidade de evidências 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 é o seu caráter bottom-up, não a sua orientação a objetos. Considere as 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 declínio da programação orientada a objetos, aliás. 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ê acumule programas como uma série de remendos.

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

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

O futuro alguma vez alcançará isso? As pessoas vêm falando sobre computação paralela como algo iminente há pelo menos 20 anos, e ela não afetou muito a prática de programação até agora. Ou não? Já os projetistas de chips têm que pensar nisso, e também as pessoas que tentam escrever software de sistema em computadores multi-cpu.

A questão real é: até que nível de abstração a paralelismo subirá? Daqui a cem anos, 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 das aplicações?

Uma coisa que parece provável é que a maioria das oportunidades de 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. Eu espero que, assim como a velocidade espantosa do hardware subjacente, o paralelismo seja algo que estará disponível se você o solicitar explicitamente, mas normalmente não usado. Isso implica que o tipo de paralelismo que teremos daqui a cem anos não será, exceto em aplicações especiais, um paralelismo maciço. Eu espero que, para programadores comuns, seja mais como poder dividir processos que acabem sendo executados em paralelo.

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

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

Quantas linguagens de programação haverá daqui a cem anos? Parece haver um grande número de novas linguagens de programação ultimamente. Parte da razão é que o hardware mais rápido permitiu que os programadores fizessem diferentes trocas entre velocidade e conveniência, dependendo da aplicação. Se essa for uma tendência real, o hardware que teremos daqui a cem anos só deve aumentá-la.

E, no entanto, pode haver apenas algumas linguagens amplamente utilizadas daqui a 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 uma versão 1 lenta, e ainda assim, com os conselhos certos de otimização para o compilador, também geraria código muito rápido quando necessário. Então, como sou otimista, vou prever que, apesar do enorme hiato que terão entre eficiência aceitável e máxima, os programadores daqui a cem anos terão linguagens que podem abranger a maior parte dele.

À medida que esse hiato se amplia, os perfis se tornarão cada vez mais importantes. Pouca atenção é dada à criação de perfis agora. Muitas pessoas ainda parecem acreditar que a maneira de obter aplicativos rápidos é escrever compiladores que gerem código rápido. À medida que o hiato 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 eu digo que pode haver apenas algumas linguagens, não estou incluindo "pequenas linguagens" específicas de domínio. Eu acho que tais linguagens embutidas são uma ótima ideia e espero que elas se proliferem. Mas eu espero que elas sejam escritas de forma tão fina que os usuários possam ver a linguagem de propósito geral subjacente.

Quem vai projetar as linguagens do futuro? Uma das tendências mais emocionantes dos últimos dez anos tem sido o surgimento 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 confusos, mas encorajadores. Há algumas ideias incrivelmente novas no Perl, por exemplo. Muitas são incrivelmente ruins, mas isso sempre é verdade para esforços ambiciosos. Na sua taxa atual de mutação, Deus sabe o que o 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. Pesquisa impõe restrições de casta restritivas. 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 da menor 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 é desalentadoramente 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 digitação estática parece excluir verdadeiras macros - sem as quais, em minha opinião, nenhuma linguagem vale a pena usar.

A tendência não é apenas para que as linguagens sejam desenvolvidas como projetos de código aberto em vez de "pesquisa", mas para que as linguagens sejam projetadas pelos programadores de aplicativos que precisam usá-las, em vez de por escritores de compiladores. Essa parece ser uma boa tendência e espero que ela continue.

Ao contrário da física em cem anos, que é quase impossível de prever, acho que pode ser possível, em princípio, projetar uma linguagem agora que atrairia 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, você pode assumir recursos ilimitados. Parece que deveríamos ser capazes de imaginar recursos ilimitados hoje tão bem quanto em cem anos.

Que programa alguém gostaria de escrever? Qualquer coisa que seja menos trabalho. Exceto não exatamente: qualquer coisa que seria menos trabalho se suas ideias sobre programação não fossem já influenciadas pelas linguagens às quais você está acostumado. 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 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ê precisa descobrir, não algo em que você naturalmente se afunda.

Uma dica útil aqui é usar o comprimento do programa como uma aproximação de quão muito 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 exatamente verdade que o programa mais curto é o que menos trabalho leva para escrever, mas é próximo o suficiente para que você esteja melhor visando o alvo sólido da brevidade do que o alvo nebuloso e próximo do menor trabalho. Então o algoritmo para o design de linguagem se torna: olhe para um programa e pergunte: existe alguma maneira de escrever isso que seja mais curta?

Em 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 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 ainda nem existem. Se o SETI@home funcionar, por exemplo, precisaremos de bibliotecas para se 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 ser capaz de projetar a linguagem central hoje. Na verdade, alguns podem argumentar que ela já foi projetada em 1958.

Se a linguagem de cem anos estivesse disponível hoje, nós a usaríamos para programar? 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 teria querido usá-las?

Em alguns aspectos, a resposta é não. As linguagens de hoje assumem uma infraestrutura que não existia em 1960. Por exemplo, uma linguagem em que a indentação é significativa, como o Python, não funcionaria muito bem em terminais de impressora. Mas deixando de lado tais problemas - supondo, por exemplo, que todos os programas fossem apenas 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 embutidos em suas ideias do que era um programa, podem ter tido dificuldade. (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 problema 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 ela poderia gerar código eficiente o suficiente para ser executado de maneira aceitável em nosso hardware. Talvez tivéssemos que dar mais conselhos de otimização do que os usuários em cem anos, mas ainda assim poderia ser um ganho líquido.

Agora temos duas ideias que, se combinadas, 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 expostas dessa maneira, é difícil não pensar: por que não tentar escrever a linguagem de cem anos agora?

Quando você está trabalhando no design de uma linguagem, acho que é bom ter um alvo como esse e mantê-lo conscientemente em mente. Quando você aprende a dirigir, um dos princípios que eles lhe ensinam é alinhar o carro não alinhando o capô com as faixas 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, essa é a resposta certa. Acho que podemos e devemos fazer o mesmo com as linguagens de programação.

Notas

Acredito que o 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 mudariam o significado de um programa correto. O Common Lisp parece ter sido o primeiro a declarar isso explicitamente.

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