Linguagens pequenas são o futuro da programação
(chreke.com)O que é uma "Little Language"?
- "Linguagens pequenas" são linguagens criadas com o objetivo de resolver um problema específico
→ SQL, RegEx, Dhall,..
→ Também são chamadas de DSL
Por que linguagens pequenas são necessárias?
- À medida que as aplicações ficaram muito mais complexas, o código-fonte também cresceu, mas ficou mais difícil de entender
- O onboarding de novos funcionários é difícil, erros acontecem por falta de compreensão das dependências, e mudanças no código vão ficando cada vez mais difíceis de gerenciar
- Nos últimos 10 anos, as bases de código cresceram de 100 a 500 vezes
- O kernel Linux começou com 10 mil linhas em 1992, mas 20 anos depois chegou a 30 milhões de linhas
- Esse código não cresceu apenas porque "há mais funcionalidades". Também porque a forma como construímos software mudou
- Assim como na construção de uma pirâmide, para colocar a última pedra é preciso haver muito mais pedras embaixo
Superando a tendência
- Será que é realmente necessário ter centenas de milhares de linhas de código para criar um OS moderno?
- Alan Kay desafiou essa suposição no programa STEPS em 2006
-
Acreditamos que criar a 'linguagem' adequada ao problema a ser resolvido torna a solução mais fácil, e faz com que ela seja menor e mais fácil de entender
- No STEPS, foi criada a linguagem Nile, que implementou funcionalidade semelhante à de um renderizador Cairo de 44.000 linhas com cerca de 300 linhas de código
Por que linguagens de alto nível não bastam?
- Não daria para simplesmente criar uma linguagem de propósito geral em um nível mais alto?
- Pessoalmente, acho que já chegamos a retornos decrescentes na expressividade das linguagens de propósito geral
- Como seria uma linguagem ainda mais alta? Se usarmos Python como exemplo, ele já está em um nível tão alto que parece pseudocódigo
- O problema das linguagens de propósito geral é que você precisa traduzir seu problema em um algoritmo e depois expressar esse algoritmo na linguagem escolhida
- Em 1986, em Programming Pearls, Jon Bentley convidou Donald Knuth e Doug McIlroy para escreverem um programa que contasse a frequência das palavras; Don escreveu, em WEB, uma variante de Pascal, ao longo de 10 páginas com estruturas de dados complexas
- Já Doug implementou isso usando uma pipeline Unix de 6 linhas com
tr,sort,uniq,sort,sede outros
Quanto menos, melhor: Less is More
- Os comandos Unix acima mostram outra característica das linguagens pequenas.
"Linguagens menos poderosas e runtimes mais poderosos" - Gonzalez fala dessa tendência em "The end of history for programming"
- Empurrar problemas do espaço do usuário para problemas de runtime
- Tornando os programas semelhantes a expressões matemáticas puras, enquanto a complexidade do runtime aumenta bastante
- Empurrar problemas do espaço do usuário para problemas de runtime
- Expressões regulares e SQL não conseguem expressar nada além de busca de texto e trabalho com banco de dados, respectivamente
- Isso contrasta com linguagens como C, que não têm runtime e nas quais tudo pode ser expresso
- As linguagens pequenas ficam na outra ponta do espectro de poder de C
- Não apenas abstraem a arquitetura do computador, mas também limitam os tipos de programas que podem ser expressos e, por design, são Turing-incomplete
- Isso pode soar muito restritivo, mas abre uma nova dimensão de possibilidades para otimização e análise estática
Análise estática
- Linguagens menos poderosas são mais fáceis de raciocinar e podem oferecer garantias mais fortes do que linguagens de propósito geral
- Por exemplo, Dhall é uma "Total Functional Programming Language" para gerar arquivos de configuração
- Isto é, para eliminar o risco de entrar em loop infinito, programas em Dhall "garantem" que "(1) não falham e (2) terminam em tempo finito"
- (1) é alcançado evitando lançar exceptions. Comandos que podem falhar retornam um valor Optional como resultado (podendo haver ou não um valor)
- (2) é alcançado ao não permitir definições recursivas
- Em outras linguagens funcionais, recursão é a forma básica de implementar loops, mas Dhall precisa depender da função embutida
fold - Não ter uma estrutura geral de loop significa que Dhall não é Turing-complete. Mas isso não é um problema, porque não é uma linguagem de propósito geral
- Quando a linguagem é pequena, raciocinar sobre ela fica muito mais fácil
- Por exemplo, é difícil verificar se um programa em Python não tem outros efeitos colaterais, mas em SQL basta verificar se a consulta começa com
SELECT
- Por exemplo, é difícil verificar se um programa em Python não tem outros efeitos colaterais, mas em SQL basta verificar se a consulta começa com
- No caso de Nile, a equipe do STEPS chegou a criar um depurador gráfico, que pode ser visto diretamente
- Isso é possível porque Nile é uma linguagem pequena e fácil de analisar
A necessidade de velocidade
- Linguagens de programação mais poderosas não apenas aumentam a chance de bugs, como também podem prejudicar o desempenho
- Por exemplo, se um programa não for expresso como algoritmo, o runtime pode escolher o algoritmo por conta própria
- Expressões lentas podem ser substituídas por rápidas (desde que se prove que produzem o mesmo resultado)
- Por exemplo, uma consulta SQL não diz como ela deve ser executada
- O mecanismo do banco de dados pode decidir livremente qual plano de execução é o mais adequado
- Se deve usar índice, índice composto, ou fazer um scan completo da tabela do banco de dados
- Motores de banco de dados modernos também coletam estatísticas sobre a distribuição dos valores em cada coluna, então conseguem escolher na hora o plano de consulta estatisticamente ótimo
- Se a consulta viesse em forma de algoritmo, isso seria impossível
- O mecanismo do banco de dados pode decidir livremente qual plano de execução é o mais adequado
- Um dos "ingredientes secretos" que tornaram a linguagem Nile tão concisa foi o "Jitblt", um compilador Just-in-Time para renderização gráfica
- Em discussões entre as equipes do STEPS e do Cairo, descobriram que muito código do Cairo era usado para otimizar manualmente operações de composição de pixels
- Em teoria, esse trabalho poderia ser delegado a um compilador
- Dan Amelang, da equipe do Cairo, se voluntariou para implementar esse compilador: o Jitblt
- Isso significou separar o trabalho de otimização do pipeline gráfico da descrição matemática pura do que deveria ser renderizado,
o que permitiu que Nile rodasse tão rápido quanto o código original do Cairo otimizado manualmente
Small languages, Big Potential (Linguagens pequenas, grande potencial)
- Então o que aconteceu com o STEPS? Será que eles criaram um OS executado por código curto o bastante para caber em uma camiseta?
- O resultado final do STEPS foi o KSWorld
- Um OS completo com editor de documentos e planilha integrados
- 17.000 linhas de código
- Um pouco longo demais para caber em uma camiseta, mas eu considero um sucesso
- A criação do KSWorld mostra que "linguagens pequenas" têm um grande potencial
- Mas ainda há muitas perguntas sem resposta
- Como essas linguagens conversariam entre si?
- Elas deveriam compilar para uma representação intermediária comum?
- Ou runtimes diferentes deveriam coexistir em paralelo e se comunicar por protocolos padronizados (como pipelines Unix, TCP/IP etc.)?
- Ou cada linguagem seria pequena o suficiente para poder ser reimplementada em várias linguagens hospedeiras?
- Ou talvez a direção certa seja combinar tudo isso?
- De qualquer forma, estou convencido de que precisamos pensar em outras maneiras de construir software
- Talvez as "linguagens pequenas" façam parte dessa história
- O importante é não continuar empilhando mais tijolos sobre tudo por tempo demais, e sim parar por tempo suficiente para imaginar algo melhor
7 comentários
"
Acreditamos que criar uma 'linguagem' adequada ao problema que precisamos resolver torna a resolução mais fácil e faz com que a solução seja menor e mais fácil de entender.
"
Ao ler essa parte, o que senti foi que, no fim das contas, 'linguagem pequena' talvez tenha o mesmo significado de framework. Como no caso de
JavaScript -> React, em que funções frequentemente usadas e padrões de design são impostos e acabam sendo transformados em uma espécie de gramática.Que tema interessante.
Pensando bem, descobri recentemente uma ferramenta de geração de DSL chamada MPS (Meta Programming System) feita pela JetBrains.
Pelo visto, isso é bem mais antigo do que eu imaginava. Fiquei interessado e queria dar uma olhada mais a fundo, mas acabei adiando por vários motivos. Se alguém aqui já usou isso, eu gostaria de ouvir algum relato de experiência.
Uau, obrigado
Li com gratidão.
Lisp todo sorridente
Achei uma história interessante e quis compartilhar a tradução.