CINCO QUESTÕES SOBRE DESIGN DE LINGUAGEM
OriginalMay 2001
(Estas são algumas notas que fiz para uma discussão em painel sobre design de linguagem de programação no MIT em 10 de maio de 2001.)
1. Linguagens de Programação São para Pessoas.
Linguagens de programação são como as pessoas conversam com os computadores. O computador ficaria tão feliz falando qualquer linguagem que fosse inequívoca. A razão pela qual nós temos linguagens de alto nível é porque as pessoas não conseguem lidar com linguagem de máquina. O objetivo das linguagens de programação é evitar que nossos pobres e frágeis cérebros humanos sejam sobrecarregados por uma massa de detalhes.
Os arquitetos sabem que alguns tipos de problemas de design são mais pessoais do que outros. Um dos problemas de design mais limpos e abstratos é projetar pontes. Lá, seu trabalho é em grande parte uma questão de abranger uma determinada distância com o mínimo de material. A outra ponta do espectro é projetar cadeiras. Os designers de cadeiras têm que passar seu tempo pensando em bundas humanas.
O software varia da mesma forma. Projetar algoritmos para roteamento de dados através de uma rede é um problema bom e abstrato, como projetar pontes. Enquanto projetar linguagens de programação é como projetar cadeiras: é tudo sobre lidar com fraquezas humanas.
A maioria de nós odeia admitir isso. Projetar sistemas de grande elegância matemática parece muito mais atraente para a maioria de nós do que agradar às fraquezas humanas. E há um papel para a elegância matemática: alguns tipos de elegância tornam os programas mais fáceis de entender. Mas a elegância não é um fim em si mesma.
E quando digo que as linguagens têm que ser projetadas para se adequar às fraquezas humanas, não quero dizer que as linguagens têm que ser projetadas para programadores ruins. Na verdade, acho que você deve projetar para o melhor programador, mas mesmo os melhores programadores têm limitações. Não acho que ninguém gostaria de programar em uma linguagem onde todas as variáveis fossem a letra x com índices inteiros.
2. Projete para Você e Seus Amigos.
Se você olhar para a história das linguagens de programação, muitas das melhores eram linguagens projetadas para seus próprios autores usarem, e muitas das piores foram projetadas para outras pessoas usarem.
Quando as linguagens são projetadas para outras pessoas, é sempre um grupo específico de outras pessoas: pessoas não tão inteligentes quanto o designer da linguagem. Então você obtém uma linguagem que fala com você. Cobol é o mais extremo caso, mas muitas linguagens são permeadas por esse espírito.
Não tem nada a ver com o quão abstrata a linguagem é. C é bem de baixo nível, mas foi projetado para seus autores usarem, e é por isso que hackers gostam dela.
O argumento para projetar linguagens para programadores ruins é que existem mais programadores ruins do que programadores bons. Isso pode ser verdade. Mas esses poucos bons programadores escrevem uma porcentagem desproporcionalmente grande do software.
Estou interessado na questão, como você projeta uma linguagem que os melhores hackers vão gostar? Acontece que acho que isso é idêntico à pergunta, como você projeta uma boa linguagem de programação?, mas mesmo que não seja, é pelo menos uma questão interessante.
3. Dê ao Programador o Máximo de Controle Possível.
Muitas linguagens (especialmente as projetadas para outras pessoas) têm a atitude de uma governanta: elas tentam impedi-lo de fazer coisas que elas acham que não são boas para você. Eu gosto do enfoque oposto: dê ao programador o máximo de controle que você puder.
Quando aprendi Lisp pela primeira vez, o que mais gostei foi que ele me considerava um parceiro igual. Nas outras linguagens que eu havia aprendido até então, havia a linguagem e havia meu programa, escrito na linguagem, e os dois eram muito separados. Mas em Lisp, as funções e macros que escrevi eram como aquelas que compunham a própria linguagem. Eu poderia reescrever a linguagem se eu quisesse. Tinha o mesmo apelo do software de código aberto.
4. Almeje a Brevidade.
A brevidade é subestimada e até desprezada. Mas se você olhar para o coração dos hackers, verá que eles realmente amam isso. Quantas vezes você já ouviu hackers falarem com carinho de como, digamos, em APL, eles podiam fazer coisas incríveis com apenas um par de linhas de código? Acho que qualquer coisa que pessoas realmente inteligentes realmente amam vale a pena prestar atenção.
Acho que quase tudo que você pode fazer para tornar os programas mais curtos é bom. Deve haver muitos funções de biblioteca; qualquer coisa que possa ser implícita deve ser; a sintaxe deve ser concisa até a falha; até os nomes das coisas devem ser curtos.
E não são apenas os programas que devem ser curtos. O manual também deve ser fino. Uma boa parte dos manuais é ocupada com esclarecimentos e reservas e avisos e casos especiais. Se você se obriga a encurtar o manual, no melhor dos casos você faz isso corrigindo as coisas na linguagem que exigiam tanta explicação.
5. Admita o Que é Hacking.
Muitas pessoas desejam que o hacking fosse matemática, ou pelo menos algo como uma ciência natural. Acho que o hacking é mais como arquitetura. Arquitetura é relacionada à física, no sentido de que os arquitetos têm que projetar edifícios que não caiam, mas o objetivo real dos arquitetos é fazer grandes edifícios, não fazer descobertas sobre estática.
O que os hackers gostam de fazer é fazer grandes programas. E acho que, pelo menos em nossas próprias mentes, temos que lembrar que é uma coisa admirável escrever grandes programas, mesmo quando esse trabalho não se traduz facilmente na moeda intelectual convencional de artigos de pesquisa. Intelectualmente, é tão válido projetar uma linguagem que os programadores vão amar quanto projetar uma horrível que incorpora alguma ideia sobre a qual você pode publicar um artigo.
1. Como Organizar Grandes Bibliotecas?
As bibliotecas estão se tornando um componente cada vez mais importante das linguagens de programação. Elas também estão ficando maiores, e isso pode ser perigoso. Se levar mais tempo para encontrar a função de biblioteca que fará o que você quer do que levaria para escrevê-la você mesmo, então todo aquele código não está fazendo nada além de tornar seu manual grosso. (Os manuais da Symbolics eram um caso em ponto.) Então acho que teremos que trabalhar em maneiras de organizar bibliotecas. O ideal seria projetá-las para que o programador pudesse adivinhar qual chamada de biblioteca faria a coisa certa.
2. As Pessoas Realmente Têm Medo da Sintaxe de Prefixo?
Este é um aberto problema no sentido de que me pergunto sobre isso há anos e ainda não sei a resposta. A sintaxe de prefixo parece perfeitamente natural para mim, exceto talvez para matemática. Mas pode ser que muito da impopularidade do Lisp seja simplesmente devido a ter uma sintaxe não familiar. Se fazer algo a respeito, se for verdade, é outra questão.
3. O Que Você Precisa para Software Baseado em Servidor?
Acho que muitas das novas aplicações mais emocionantes que serão escritas nos próximos vinte anos serão aplicações baseadas na Web, ou seja, programas que ficam no servidor e conversam com você através de uma Web navegador. E para escrever esses tipos de programas, podemos precisar de alguns coisas novas.
Uma coisa que precisaremos é suporte para a nova maneira como os servidores aplicativos são lançados. Em vez de ter um ou dois grandes lançamentos a ano, como software de desktop, aplicativos baseados em servidor são lançados como um série de pequenas alterações. Você pode ter até cinco ou dez lançamentos por dia. E como regra, todos sempre usarão a versão mais recente.
Você sabe como você pode projetar programas para serem depuráveis? Bem, o software baseado em servidor também tem que ser projetado para ser modificável. Você tem que ser capaz de alterá-lo facilmente, ou pelo menos saber o que é uma pequena mudança e o que é uma mudança monumental.
Outra coisa que pode acabar sendo útil para servidores software, surpreendentemente, são as continuações. Em software baseado na Web você pode usar algo como estilo de passagem de continuação para obter o efeito de subrotinas no inerentemente mundo sem estado de uma sessão da Web. Talvez valha a pena ter continuações reais, se não fosse muito caro.
4. Quais Novas Abstrações Restaram para Ser Descobertas?
Não sei o quão razoável é essa esperança, mas uma coisa que eu realmente adoraria fazer, pessoalmente, é descobrir uma nova abstração - algo que faria tantas diferenças quanto ter funções de primeira classe ou recursão ou até mesmo parâmetros de palavra-chave. Isso pode ser um impossível sonho. Essas coisas não são descobertas com tanta frequência. Mas estou sempre procurando.
1. Você Pode Usar Qualquer Linguagem Que Quiser.
Escrevendo aplicativo programas costumavam significar escrever software de desktop. E em desktops software, há um grande viés para escrever o aplicativo na mesma linguagem do sistema operacional. E então, há dez anos, escrever software significava quase escrever software em C. Eventualmente, uma tradição evoluiu: aplicativos não devem ser escritos em linguagens incomuns. E essa tradição teve tanto tempo para se desenvolver que pessoas não técnicas como gerentes e capitalistas de risco também aprenderam.
O software baseado em servidor elimina todo esse modelo. Com servidores software, você pode usar qualquer linguagem que quiser. Quase ninguém entende isso ainda (especialmente não gerentes e capitalistas de risco). Alguns hackers entendem, e é por isso que até ouvimos sobre novas linguagens indy como Perl e Python. Não estamos ouvindo sobre Perl e Python porque as pessoas estão usando-os para escrever Windows aplicativos.
O que isso significa para nós, como pessoas interessadas em projetar programação linguagens, é que agora há potencialmente um público real para nosso trabalho.
2. A Velocidade Vem dos Perfiladores.
Projetistas de linguagem, ou pelo menos implementadores de linguagem, gostam de escrever compiladores que geram rápidos código. Mas não acho que seja isso que torna as linguagens rápidas para os usuários. Knuth apontou há muito tempo que a velocidade só importa em alguns críticos gargalos. E qualquer um que já tentou sabe que você não pode adivinhar onde estão esses gargalos. Perfiladores são a resposta.
Os projetistas de linguagem estão resolvendo o problema errado. Os usuários não precisam de benchmarks para rodar rápido. O que eles precisam é de uma linguagem que possa mostrar a eles quais partes de seus próprios programas precisam ser reescritas. É isso de onde vem a velocidade na prática. Então talvez seja uma rede ganho se os implementadores de linguagem gastassem metade do tempo que gastariam fazendo otimizações de compilador e gastassem em escrever um bom perfilador em vez disso.
3. Você Precisa de um Aplicativo para Impulsionar o Design de uma Linguagem.
Isso pode não ser uma regra absoluta, mas parece que as melhores linguagens todas evoluíram junto com algum aplicativo que estavam sendo usadas para escrever. C foi escrito por pessoas que precisavam dele para programação de sistemas. Lisp foi desenvolvido em parte para fazer diferenciação simbólica, e McCarthy estava tão ansioso para começar que estava escrevendo diferenciação programas até mesmo no primeiro artigo sobre Lisp, em 1960.
É especialmente bom se seu aplicativo resolver algum novo problema. Isso tenderá a levar sua linguagem a ter novos recursos que os programadores precisam. Pessoalmente, estou interessado em escrever uma linguagem que seja boa para escrever aplicativos baseados em servidor.
[Durante o painel, Guy Steele também fez esse ponto, com o sugestão adicional de que o aplicativo não deve consistir em escrever o compilador para sua linguagem, a menos que sua linguagem acontece de ser destinado a escrever compiladores.]
4. Uma Linguagem Tem Que Ser Boa para Escrever Programas Descartáveis.
Você sabe o que é um programa descartável: algo que você escreve rapidamente para alguma tarefa limitada. Acho que se você olhasse ao redor, descobriria que muitos programas grandes e sérios começaram como programas descartáveis. Eu não ficaria surpreso se a maioria dos programas começasse como descartáveis programas. E então, se você quiser criar uma linguagem que seja boa para escrever software em geral, ela tem que ser boa para escrever descartáveis programas, porque essa é a fase larval da maioria dos softwares.
5. A Sintaxe Está Conectada à Semântica.
É tradicional pensar em sintaxe e semântica como sendo completamente separadas. Isso vai parecer chocante, mas pode ser que elas não sejam. Acho que o que você quer em sua linguagem pode estar relacionado a como você o expressa.
Estava conversando recentemente com Robert Morris, e ele apontou que sobrecarga de operador é uma vitória maior em linguagens com infixo sintaxe. Em uma linguagem com sintaxe de prefixo, qualquer função que você define é efetivamente um operador. Se você quiser definir um mais para um novo tipo de número que você inventou, você pode simplesmente definir uma nova função para adicioná-los. Se você fizer isso em uma linguagem com sintaxe de infixo, há uma grande diferença na aparência entre o uso de um operador sobrecarregado e uma chamada de função.
1. Novas Linguagens de Programação.
Na década de 1970 era moda projetar novas linguagens de programação. Recentemente não tem sido. Mas acho que o software baseado em servidor tornará novos linguagens na moda novamente. Com software baseado em servidor, você pode usar qualquer linguagem que quiser, então se alguém projetar uma linguagem que realmente parece melhor do que outras que estão disponíveis, haverá pessoas que correm o risco e a usam.
2. Tempo Compartilhado.
Richard Kelsey deu isso como uma ideia cujo tempo chegou novamente no último painel, e concordo totalmente com ele. Meu palpite (e o palpite da Microsoft, parece) é que muito processamento irá se mover do desktop para servidores remotos. Em outras palavras, o tempo compartilhado está de volta. E acho que haverá necessidade de suporte para isso no nível da linguagem. Por exemplo, sei que Richard e Jonathan Rees fizeram muito trabalho implementando processo agendamento dentro do Scheme 48.
3. Eficiência.
Recentemente, estava começando a parecer que os computadores estavam finalmente rápidos o suficiente. Cada vez mais estávamos começando a ouvir sobre bytecode, o que implica para mim, pelo menos, que sentimos que temos ciclos de sobra. Mas não acho que teremos, com servidores software. Alguém vai ter que pagar pelos servidores que o software é executado, e o número de usuários que eles podem suportar por máquina será o divisor de seu custo de capital.
Então acho que a eficiência vai importar, pelo menos em computação gargalos. Será especialmente importante fazer i/o rápido, porque aplicativos baseados em servidor fazem muito i/o.
Pode acabar que o bytecode não é uma vitória, no final. Sol e A Microsoft parece estar se enfrentando em uma espécie de batalha do byte códigos no momento. Mas eles estão fazendo isso porque o bytecode é um lugar conveniente para se inserir no processo, não porque bytecode é em si uma boa ideia. Pode acabar que isso todo o campo de batalha é contornado. Isso seria meio engraçado.
1. Clientes.
Este é apenas um palpite, mas meu palpite é que o modelo vencedor para a maioria dos aplicativos será puramente baseado em servidor. Projetar software que funciona com a suposição de que todos terão seu cliente é como projetar uma sociedade com a suposição de que todos serão honestos. Certamente seria conveniente, mas você tem que assumir que isso nunca vai acontecer.
Acho que haverá uma proliferação de dispositivos que têm algum tipo de acesso à Web, e tudo o que você poderá assumir sobre eles é que eles podem suportar html e formulários simples. Você terá um navegador no seu celular? Haverá um telefone no seu palm piloto? Seu blackberry vai ter uma tela maior? Você será capaz de navegar na Web no seu gameboy? Seu relógio? Eu não sei. E não preciso saber se aposto em tudo apenas no servidor. É muito mais robusto ter todos os cérebros no servidor.
2. Programação Orientada a Objetos.
Eu percebo que esta é uma questão controversa, mas não acho que a programação orientada a objetos seja tão importante. Acho que é um bom modelo para certos tipos de aplicativos que precisam desse tipo específico de estrutura de dados, como sistemas de janelas, simulações e programas de cad. Mas eu não vejo por que deveria ser o modelo para toda a programação.
Acho que parte da razão pela qual as pessoas em grandes empresas gostam da programação orientada a objetos é porque ela gera muito do que parece trabalho. Algo que pode ser naturalmente representado como, digamos, uma lista de inteiros, agora pode ser representado como uma classe com todos os tipos de andaimes e agitação e agitação.
Outra atração de programação orientada a objetos é que os métodos lhe dão alguns dos efeito de funções de primeira classe. Mas isso é uma velha notícia para Lisp programadores. Quando você tem funções de primeira classe reais, você pode simplesmente usá-las da maneira que for apropriada à tarefa em questão, em vez de forçar tudo em um molde de classes e métodos.
O que isso significa para o design de linguagem, acho, é que você não deve construir a programação orientada a objetos com muita profundidade. Talvez o resposta é oferecer coisas mais gerais e subjacentes, e deixar as pessoas projetarem quaisquer sistemas de objetos que quiserem como bibliotecas.
3. Design por Comitê.
Ter sua linguagem projetada por um comitê é uma grande armadilha, e não apenas pelas razões que todos conhecem. Todos sabem que os comitês tendem a gerar projetos desajeitados e inconsistentes. Mas acho que um perigo maior é que eles não correrão riscos. Quando uma pessoa está no comando, ela pode correr riscos que um comitê nunca concordaria.
É necessário correr riscos para projetar uma boa linguagem, no entanto? Muitas pessoas podem suspeitar que o design de linguagem é algo em que você deve ficar bem próximo à sabedoria convencional. Aposto que isso não é verdade. Em tudo mais que as pessoas fazem, a recompensa é proporcional ao risco. Por que o design de linguagem deveria ser diferente?