O QUE TORNOU O LISP DIFERENTE
OriginalDecember 2001 (rev. May 2002)
(Este artigo surgiu em resposta a algumas perguntas na lista de discussão LL1. Ele agora está incorporado em Revenge of the Nerds.)
Quando McCarthy projetou o Lisp no final dos anos 1950, ele era uma partida radical das linguagens existentes, a mais importante das quais era Fortran.
O Lisp incorporou nove novas ideias:
1. Condicionais. Um condicional é uma construção if-then-else. Nós os damos como certos agora. Eles foram inventados por McCarthy no curso do desenvolvimento do Lisp. (Fortran naquela época só tinha um goto condicional, baseado no comando de ramificação no hardware subjacente.) McCarthy, que estava no comitê do Algol, conseguiu condicionaiss no Algol, de onde eles se espalharam para a maioria das outras linguagens.
2. Um tipo de função. No Lisp, funções são objetos de primeira classe -- elas são um tipo de dados como inteiros, strings, etc, e têm uma representação literal, podem ser armazenadas em variáveis, podem ser passadas como argumentos, e assim por diante.
3. Recursão. A recursão existia como um conceito matemático antes do Lisp, é claro, mas o Lisp foi a primeira linguagem de programação a suportar isso. (É discutível que seja implícito ao tornar as funções de primeira classe objetos.)
4. Um novo conceito de variáveis. No Lisp, todas as variáveis são efetivamente ponteiros. Valores são o que têm tipos, não variáveis, e atribuir ou vincular variáveis significa copiar ponteiros, não o que eles apontam.
5. Coleta de lixo.
6. Programas compostos de expressões. Programas Lisp são árvores de expressões, cada uma das quais retorna um valor. (Em alguns Lisps, expressões podem retornar vários valores.) Isso contrasta com Fortran e a maioria das linguagens que o sucederam, que distinguem entre expressões e instruções.
Era natural ter essa distinção em Fortran porque (não surpreendentemente em uma linguagem onde o formato de entrada era cartões perfurados) a linguagem era orientada a linhas. Você não podia aninhar instruções. E assim, enquanto você precisava de expressões para que a matemática funcionasse, não havia nenhum ponto em fazer qualquer outra coisa retornar um valor, porque não poderia haver nada esperando por ele.
Essa limitação desapareceu com a chegada de linguagens estruturadas em blocos, mas naquela época já era tarde demais. A distinção entre expressões e instruções estava arraigada. Ela se espalhou de Fortran para Algol e daí para seus descendentes.
Quando uma linguagem é feita inteiramente de expressões, você pode compor expressões como quiser. Você pode dizer ou (usando a sintaxe Arc)
(if foo (= x 1) (= x 2))
ou
(= x (if foo 1 2))
7. Um tipo de símbolo. Símbolos diferem de strings no sentido de que você pode testar a igualdade comparando um ponteiro.
8. Uma notação para código usando árvores de símbolos.
9. A linguagem inteira sempre disponível. Não há uma distinção real entre tempo de leitura, tempo de compilação e tempo de execução. Você pode compilar ou executar código durante a leitura, ler ou executar código durante a compilação e ler ou compilar código em tempo de execução.
Executar código em tempo de leitura permite que os usuários reprogramem a sintaxe do Lisp; executar código em tempo de compilação é a base das macros; compilar em tempo de execução é a base do uso do Lisp como uma linguagem de extensão em programas como o Emacs; e ler em tempo de execução permite que os programas se comuniquem usando s-expressões, uma ideia recentemente reinventada como XML.
Quando o Lisp foi inventado pela primeira vez, todas essas ideias estavam muito distantes da prática de programação comum, que era ditada em grande parte pelo hardware disponível no final dos anos 1950.
Com o tempo, a linguagem padrão, incorporada em uma sucessão de linguagens populares, tem evoluído gradualmente em direção ao Lisp. 1-5 agora são generalizados. 6 está começando a aparecer na corrente principal. Python tem uma forma de 7, embora não pareça haver nenhuma sintaxe para isso. 8, que (com 9) é o que torna as macros Lisp possíveis, ainda é exclusivo do Lisp, talvez porque (a) requer esses parênteses, ou algo igualmente ruim, e (b) se você adicionar esse incremento final de poder, você não pode mais afirmar ter inventado uma nova linguagem, mas apenas ter projetado um novo dialeto do Lisp ; -)
Embora útil para programadores de hoje, é estranho descrever o Lisp em termos de sua variação dos expedientes aleatórios que outras linguagens adotaram. Essa não era, provavelmente, a forma como McCarthy pensava sobre isso. O Lisp não foi projetado para corrigir os erros em Fortran; ele surgiu mais como um subproduto de uma tentativa de axiomatizar a computação.