Artigos aprofundados sobre a tecnologia que molda o que vem a seguir.

Por que Lisp ainda importa depois de seis décadas

Lisp tem mais de 65 anos e ainda influencia o design de linguagens modernas. Veja o que o faz perdurar e o que desenvolvedores podem aprender com ele.

Árvore antiga com galhos formados por parênteses aninhados, carregando frutos brilhantes

A cada poucos anos, alguém escreve um ensaio dizendo que “Lisp está morto”, e a cada poucos anos, outra pessoa aponta que metade dos recursos da sua linguagem moderna favorita foi copiada do Lisp. Coleta de lixo, funções de primeira classe, closures, tipagem dinâmica, homoiconicidade, desenvolvimento guiado por REPL, macros — tudo foi inventado ou popularizado no Lisp antes de a maioria dos desenvolvedores de hoje nascer. Lisp é o tipo de projeto que leva décadas para ser plenamente apreciado.

E, mesmo assim. Pergunte a um desenvolvedor em atividade se ele já usou Lisp e a maioria dirá que não. Pergunte se ele começaria um projeto de produção em Lisp e a maioria vai olhar torto para você. Existe um paradoxo aqui: as ideias do Lisp conquistaram o mundo da programação, mas a linguagem em si continua de nicho. Entender por quê é mais interessante do que os argumentos do tipo “Lisp bom, outras linguagens ruins” que aparecem na maior parte da defesa do Lisp.

O que o Lisp Realmente Acertou

Lisp foi criado por John McCarthy em 1958. Para ter uma noção, o FORTRAN tinha apenas um ano de vida. O COBOL ainda não existia. O minicomputador PDP-1 só chegaria dois anos depois. O Lisp foi projetado no papel e implementado em um IBM 704 — uma máquina que ocupava uma sala inteira e tinha palavras de 36 bits.

Apesar disso, McCarthy tomou decisões de design que continuam relevantes seis décadas depois. As mais importantes:

Código como Dado (Homoiconicidade)

Na maioria das linguagens, código e dados são coisas fundamentalmente diferentes. Você escreve código em uma sintaxe, e ele manipula estruturas de dados. Em Lisp, código é dado. Um programa em Lisp é feito de listas. A expressão (+ 1 2) é ao mesmo tempo uma chamada de função que soma 1 e 2, e uma lista com três elementos: o símbolo +, o número 1 e o número 2. Você pode manipular essa lista — reorganizá-la, adicionar elementos, transformá-la — e depois executar o resultado.

;; This is a function call
(+ 1 2)  ; => 3
;; This is a list containing the same elements
'(+ 1 2)  ; => (+ 1 2)
;; You can build code as data and then evaluate it
(def my-expr '(+ 1 2))
(eval my-expr)  ; => 3
;; Or transform it
(def doubled (list '* 2 my-expr))
;; doubled is now (* 2 (+ 1 2))
(eval doubled)  ; => 6

Isso parece uma curiosidade até você perceber o que possibilita: programas que escrevem programas. Macros em Lisp não fazem substituição de texto como as macros do pré-processador C. Elas recebem a estrutura real do programa como uma estrutura de dados, a transformam usando todo o poder da linguagem e devolvem uma nova estrutura de programa. Isso é geração de código em tempo de compilação, com o próprio compilador funcionando como sua API.

O REPL como Ambiente de Desenvolvimento

O Lisp foi pioneiro no Read-Eval-Print Loop — a ideia de que você deveria poder digitar uma expressão, vê-la avaliada imediatamente e ver o resultado. Isso parece trivial numa época em que toda linguagem tem um REPL, mas o REPL do Lisp vai além da maioria.

Em Common Lisp ou Clojure, você não testa apenas expressões isoladas no REPL. Você desenvolve sistemas inteiros de forma interativa. Define uma função, testa, redefine, tudo isso enquanto o programa continua rodando. Pode inspecionar e modificar o estado em execução. Pode recompilar uma única função sem reiniciar a aplicação. O ciclo de desenvolvimento não é escrever-compilar-executar-depurar — é uma conversa contínua com um sistema vivo.

Desenvolvedores de Clojure, em particular, costumam trabalhar assim: conectam o editor a um REPL em execução, escrevem código no editor, avaliam expressões individuais com um atalho de teclado e veem os resultados na hora. O ciclo de feedback é medido em milissegundos, não em minutos. Depois que você trabalha dessa forma, o tradicional ciclo de editar-compilar-reiniciar parece uma comunicação por correspondência.

Sintaxe Mínima, Flexibilidade Máxima

A sintaxe do Lisp — ou a ausência dela — é seu recurso mais polarizador. Não há formas especiais para instruções if, laços for ou definições de classe. Tudo é uma lista com o operador na frente: (if condition then-expr else-expr), (defn name [args] body), (for [x (range 10)] (* x x)). Os parênteses que incomodam quem está começando são o preço de entrada para a linguagem com a sintaxe mais regular já projetada.

Essa regularidade tem um benefício prático: as ferramentas. Quando toda construção segue o mesmo padrão (operator operands...), os editores conseguem indentar, refatorar e navegar pelo código de forma estrutural com confiança. “Selecione a expressão envolvente” é inequívoco em Lisp — são sempre os parênteses correspondentes. Em linguagens com sintaxes variadas, a edição estrutural ainda é um problema não resolvido. Em Lisp, ele está resolvido desde os anos 1960.

Por que o Lisp Não Venceu

Se o Lisp é tão bom, por que nem todo mundo o usa? A resposta padrão dos defensores do Lisp é “a indústria está errada”, o que não ajuda e é quase sempre falso. O Lisp não alcançou adoção massiva por motivos reais e não triviais.

  • A lacuna do ecossistema. Bibliotecas importam mais do que recursos da linguagem na maior parte do trabalho prático. O Python não é popular por causa da beleza da sintaxe — é popular porque o pip install dá acesso instantâneo a milhares de pacotes bem mantidos para ciência de dados, desenvolvimento web, machine learning e tudo mais. Os ecossistemas Lisp (Common Lisp, Scheme, Clojure) são sólidos, mas menores. Você vai gastar mais tempo escrevendo coisas do zero ou adaptando bibliotecas menos mantidas.
  • A curva de aprendizado está concentrada no início. A sintaxe com parênteses é trivial depois que você a internaliza, mas é uma barreira real para iniciantes. Mais importante: escrever Lisp idiomático exige pensar de um jeito que soa estranho para quem vem de linguagens procedurais ou orientadas a objetos. A recompensa vem depois, mas muitos desenvolvedores desistem antes de chegar lá.
  • Fragmentação. “Lisp” não é uma linguagem única — é uma família. Common Lisp, Scheme, Racket, Clojure, Emacs Lisp, Hy, Janet — cada uma com pontos fortes, ecossistemas e comunidades diferentes. Essa fragmentação impede a concentração de esforços que faz os ecossistemas crescerem.
  • O apoio corporativo importa. A Java teve a Sun. C# teve a Microsoft. Go teve o Google. Python teve o Google e uma enorme comunidade de ciência de dados. A linguagem da família Lisp mais bem-sucedida em produção, Clojure, ganhou tração em parte porque Rich Hickey é um pensador e comunicador excepcionalmente claro — mas ainda não tem o respaldo institucional que impulsiona a adoção massiva.

Clojure: Lisp que Aprendeu com a História

Clojure merece atenção especial porque mostra como pegar os pontos fortes do Lisp e torná-los práticos para o desenvolvimento de software moderno. Rich Hickey projetou o Clojure em 2007 com plena consciência de por que os Lisps anteriores não alcançaram adoção massiva, e fez escolhas de compromisso deliberadas.

  • Roda na JVM. Em vez de construir um ecossistema separado do zero, o Clojure roda na Java Virtual Machine e pode usar qualquer biblioteca Java diretamente. Precisa de um driver de banco de dados? Use o Java. Precisa de um cliente HTTP? Use o Java. Essa única decisão deu ao Clojure acesso a milhares de bibliotecas testadas em batalha desde o primeiro dia.
  • Imutabilidade por padrão. As estruturas de dados centrais do Clojure — listas, vetores, mapas, conjuntos — são imutáveis. Você não modifica um mapa; cria um novo com as mudanças. Isso elimina categorias inteiras de bugs de concorrência e torna os programas mais fáceis de raciocinar. As estruturas de dados persistentes por baixo dos panos compartilham estrutura para tornar isso eficiente.
  • Primitivas de concorrência práticas. Atoms, refs, agents — o Clojure oferece múltiplos modelos de concorrência, cada um adequado a padrões diferentes. Isso não era elegância teórica; era a experiência direta de Hickey com a dor de estado mutável compartilhado em aplicações Java de produção.
  • ClojureScript. O Clojure compila para JavaScript, o que lhe dá acesso aos ecossistemas do navegador e do Node.js. Escreva o backend em Clojure, o frontend em ClojureScript e compartilhe código entre eles. É a mesma promessa do TypeScript ou do Kotlin Multiplatform, só que chegou antes.

O que as Linguagens Modernas Pegaram Emprestado

Mesmo que você nunca escreva uma linha de Lisp, usa as ideias dele todos os dias. A influência é tão difundida que rastreá-la se torna um exercício de ver o quão profunda ela é.

map, filter e reduce do JavaScript são descendentes diretos das funções de processamento de listas do Lisp — a linguagem leva o nome delas (LISt Processing). As list comprehensions do Python são açúcar sintático para as mesmas operações. O pattern matching do Rust remonta, passando pelo ML, às expressões cond do Lisp. As closures do Swift, a sintaxe de lambda do Kotlin, a API de streams do Java — tudo isso são conceitos do Lisp vestindo outras roupas.

Os sistemas de macros do Rust (macro_rules! e macros procedurais), Elixir, Nim e Julia são diretamente inspirados nas macros do Lisp — embora nenhum alcance exatamente a mesma naturalidade, porque nenhuma dessas linguagens tem sintaxe homoicônica. Quando o seu código é dado, macros são triviais. Quando o código tem sintaxe complexa, as macros precisam fazer parse e gerar essa sintaxe, o que adiciona atrito.

O desenvolvimento guiado por REPL virou norma em ciência de dados (os notebooks Jupyter são essencialmente REPLs com persistência), e ferramentas como Figwheel e shadow-cljs trouxeram hot-reloading para o desenvolvimento frontend — uma ideia que veio diretamente da tradição Lisp de desenvolver contra um sistema em execução.

Vale a Pena Aprender Lisp?

A resposta honesta depende do que você quer obter com isso.

Se você quer se tornar um programador melhor expandindo a forma como pensa sobre código: sim, com certeza. Aprender Lisp — especificamente, aprender a pensar em termos de transformação de dados, estruturas recursivas e código-como-dado — vai mudar a forma como você aborda problemas em qualquer linguagem. É como aprender programação funcional: mesmo que você nunca use Haskell em produção, os conceitos fazem você escrever Python e JavaScript melhores.

Se você quer construir software de produção com Lisp: Clojure é a escolha prática. Tem um ecossistema real, uma comunidade profissional e empresas (Nubank, Walmart, CircleCI) rodando-o em escala. Common Lisp é viável, mas de nicho — você vai gastar mais tempo com infraestrutura e menos com o seu problema de fato. Scheme e Racket são excelentes para educação e pesquisa em linguagens, mas menos práticos para desenvolvimento de propósito geral.

Se você está curioso, mas não está pronto para se comprometer, leia algum código em Clojure. Não tutoriais — código de produção de verdade. Observe como desenvolvedores de Clojure compõem pequenas funções, como usam as macros de encadeamento (-> e ->>) para construir pipelines de dados, como modelam domínios com mapas simples em vez de classes. Você vai ver um estilo de programação mais conciso, mais componível e mais focado no fluxo de dados do que o que encontra nas bases de código OOP mainstream.

A longevidade do Lisp não é nostalgia. É o resultado de acertar algumas coisas fundamentais tão bem que seis décadas de design de linguagens não conseguiram melhorá-las. Os parênteses são estranhos. O ecossistema é menor do que você gostaria. Mas as ideias são atemporais, e se você passar um tempo com elas, vai se pegar escrevendo um código melhor em qualquer linguagem que use no dia a dia.