Prólogo
Last updated
Was this helpful?
Last updated
Was this helpful?
Educadores, generais, nutricionistas, psicologistas e pais programam. Exércitos, estudantes, e algumas sociedades são programados. Um ataque a grandes problemas emprega uma sucessão de programas, muitos dos quais surgem no caminho. Estes programas estão repletos de questões que parecem ser específicas ao problema em mão. Para apreciar a programação como uma atividade intelectual por si mesma, você deve recorrer à programação de computadores; você deve ler e escrever programas de computador — muitos deles. Não importa muito sobre o que são os programas ou para quais aplicações eles servem. O que realmente importa é quão bem eles executam e quão fluidamente eles se encaixam com outros programas na criação de programas ainda maiores. O programador deve perseguir tanto a perfeição parcial quanto a adequação coletiva. Neste livro o uso da palavra "programa" é focado na criação, execução e estudo de programas escritos em um dialeto de Lisp para execução em um computador digital. Ao utilizar Lisp nós não restringimos ou limitamos o que poderá ser programado, mas apenas a notação pela qual nossos programas serão descritos.
Nosso tráfego com o assunto deste livro nos envolve com três focos de fenômenos: a mente humana, coleções de programas de computador, e o computador. Cada programa de computador é um modelo eclodido na mente de um processo real ou mental. Tais processos, decorrentes da experiência e do pensamento humanos, são gigantes em número, intrincados em seus detalhes e, a qualquer momento, apenas parcialmente entendidos. Eles são modelados para a nossa satisfação permanente, raramente por nossos programas de computador. Portanto, embora nossos programas sejam coleções de símbolos cuidadosamente elaboradas, mosaicos de funções interligadas, eles evoluem continuamente: nós os modificamos conforme nossa percepção do modelo se aprofunda, amplia, generaliza até que o modelo finalmente atinja um local metaestável dentro de ainda outro modelo com o qual nós lutemos. A fonte da satisfação associada com a programação de computadores é o desdobramento contínuo, na mente e no computador, dos mecanismos expressos como programas e da explosão de percepção que eles geram. Se a arte é a interpretação de nossos sonhos, o computador é a sua execução no aspecto de programas!
Com todo seu poder, o computador é capataz severo. Seus programas devem estar corretos, e o que desejamos dizer deve ser dito com precisão em cada detalhes. Como em qualquer outra atividade simbólica, nos convencemos da verdade do programa por meio do argumento. O próprio Lisp pode receber uma semântica (outro modelo, a propósito), e se a função de um programa pode ser especificada, digamos, no cálculo de predicados, os métodos de prova da lógica podem ser usados para formar um argumento de exatidão aceitável. Infelizmente, à medida que os programas ficam grandes e complicados, como quase sempre acontece, a adequação, consistência e exatidão das próprias especificações tornam-se abertas a dúvidas, de modo que que argumentos formais completos de exatidão raramente acompanham grandes programas. Uma vez que grandes programas crescem de pequenos, é crucial que desenvolvamos um arsenal de estruturas de programas padrão de cuja exatidão tenhamos certeza — nós as chamamos de idiomas — e aprendamos a combiná-las em estruturas maiores usando técnicas organizacionais de valor comprovado. Essas técnicas são tratadas em detalhes neste livro, e entendê-las é essencial para a participação no empreendimento Prometeico — rebeldemente criativo e inovador — chamado programação. Mais do que qualquer outra coisa, a descoberta e o domínio de técnicas organizacionais poderosas aceleram nossa capacidade de criar programas grandes e significativos. Por outro lado, uma vez que escrever grandes programas é muito trabalhoso, somos estimulados a inventar novos métodos para reduzir a massa de funções e detalhes a serem equipados em grandes programas.
Ao contrário dos programas, os computadores devem obedecer às leis da física. Se eles desejam ter um desempenho rápido — alguns nanossegundos por mudança de estado — eles devem transmitir elétrons apenas a pequenas distâncias (no máximo 45 centímetros). O calor gerado pelo grande número de dispositivos tão concentrados no espaço deve ser removido. Uma requintada arte de engenharia foi desenvolvida equilibrando a multiplicidade de funções e a densidade de dispositivos. Em qualquer caso, o hardware sempre opera em um nível mais primitivo do que aquele em que desejamos programar. Os processos que transformam nossos programas Lisp em programas de "máquina" são eles próprios modelos abstratos que programamos. Seu estudo e criação fornecem uma grande compreensão dos programas organizacionais associados à programação de modelos arbitrários. Claro que o próprio computador pode ser modelado dessa forma. Pense nisso: o comportamento do menor elemento físico de comutação é modelado pela mecânica quântica descrita por equações diferenciais cujo comportamento detalhado é capturado por aproximações numéricas representadas em programas de computadores em execução em computadores compostos por ...!
Não é apenas uma questão de conveniência tática identificar separadamente os três focos. Mesmo que, como dizem, esteja tudo na cabeça, essa separação lógica induz uma aceleração do tráfego simbólico entre esses focos cuja riqueza, vitalidade e potencial são excedidos na experiência humana apenas pela evolução da própria vida. Na melhor das hipóteses, os relacionamentos entre os focos são metaestáveis. Os computadores nunca são grandes ou rápidos o suficiente. Cada avanço na tecnologia de hardware leva a empreendimentos de programação mais massivos, novos princípios organizacionais e um enriquecimento de modelos abstratos. Todo leitor deve se perguntar periodicamente "Para que fim, para que fim?" - mas não pergunte com muita frequência, para não perder a diversão da programação para a constipação da filosofia agridoce.
Entre os programas que escrevemos, alguns (mas nunca o suficiente) executam uma função matemática precisa, como ordenação ou encontrar o máximo de uma sequência de números, determinar a primalidade ou encontrar a raiz quadrada. Chamamos tais programas de algoritmos, e muito se sabe sobre seu comportamento otimizado, particularmente com respeito aos dois parâmetros importantes: tempo de execução e requisitos de armazenamento de dados. Um programador deve adquirir bons algoritmos e idiomas. Mesmo que alguns programas resistam a especificações precisas, é responsabilidade do programador estimar, e sempre tentar melhorar, seu desempenho.
Lisp é um sobrevivente, tendo estado em uso por cerca de um quarto de século.*1 Entre as linguagens de programação ativas, apenas Fortran teve uma vida mais longa. Ambas as linguagens suportaram as necessidades de programação de importantes áreas de aplicação, Fortran para a computação científica e de engenharia e Lisp para inteligência artificial. Essas duas áreas continuam a ser importantes, e seus programadores são tão dedicados a essas duas linguagens que Lisp e Fortran podem, muito bem, continuar em uso ativo por pelo menos mais um quarto de século.
Lisp evolui. O dialeto Scheme usado neste texto evoluiu do Lisp original e difere dele em vários aspectos importantes, incluindo escopo estático para vinculação de variáveis e por permitir que funções retornem funções como valores. Em sua estrutura semântica, Scheme é tão parecida com Algol 60 quanto com os primeiros Lisps. Algol 60, nunca mais sendo uma linguagem ativa, vive nos genes de Scheme e Pascal. Seria difícil encontrar duas linguagens que sejam a moeda comunicante de duas culturas mais diferentes que aquelas reunidas em torno dessas duas linguagens. Pascal é para a construção de pirâmides — estruturas estáticas imponentes, de tirar o fôlego, construídas por exércitos empurrando blocos pesados em suas posições. Lisp é para a construção de organismos — estruturas dinâmicas imponentes, de tirar o fôlego, construídas por esquadrões ajustando miríades de simples organismos flutuantes em suas posições. Os princípios organizacionais utilizados são os mesmos em ambos os casos, exceto por uma extraordinariamente importante diferença: A funcionalidade discricionária exportável confiada ao programador Lisp individual é mais de uma ordem de magnitude maior do que aquela encontrada nos empreendimentos em Pascal. Programas Lisp inflam as bibliotecas com funções cuja utilidade transcende a aplicação que as produziu. A lista, estrutura de dados nativa do Lisp, é a grande responsável por esse crescimento de utilidade. A estrutura simples e a aplicabilidade de lista se refletem em funções que são surpreendentemente não-. Em Pascal, a abundância de estruturas de dados declaráveis induz a uma especialização dentro das funções que inibe e penaliza a colaboração casual. É melhor ter 100 funções operando em uma estrutura de dados do que 10 funções operando em 10 estruturas de dados. Como resultado, a pirâmide permanecer inalterada por um milênio; o organismo deve evoluir ou perecer.
Para ilustrar essa diferença, compare o tratamento do material e dos exercícios deste livro com o de qualquer texto de curso iniciante usando Pascal. Não tenha a ilusão de que este é um texto digerível apenas no MIT, peculiar à raça ali encontrada. É precisamente o que um livro sério sobre programação Lisp deve ser, não importa quem seja o aluno ou onde seja usado.
Note que este é um texto sobre programação, ao contrário da maioria dos livros sobre Lisp, que são usados como preparação para o trabalho em Inteligência Artificial. Afinal, as preocupações críticas de programação da engenharia de software e inteligência artificial tendem a se aglutinar à medida que os sistemas sob investigação se tornam maiores. Isso explica por que existe tanto interesse crescente em Lisp fora da inteligência artificial.
Como seria de se esperar de seus objetivos, a pesquisa de inteligência artificial gera muitos problemas de programação significativos. Em outras culturas de programação, essa enxurrada de problemas gera novas linguagens. De fato, em qualquer tarefa de programação muito grande, um princípio de organização útil é controlar e isolar o tráfego dentro dos módulos de tarefas por meio da invenção da linguagem. Essas linguagens tendem a se tornar menos primitivas à medida que nos aproximamos dos limites do sistema onde nós, humanos, interagimos com mais frequência. Como resultado, tais sistemas contém complexas funções de processamento de linguagem replicadas muitas vezes. Lisp tem uma sintaxe e semântica tão simples que a sua análise pode ser tratada como uma tarefa elementar. Assim, a tecnologia de análise quase não desempenha nenhum papel em programas Lisp, e a construção de processadores de linguagens raramente é um impedimento para a taxa de crescimento e mudança de grandes sistemas Lisp. Finalmente, é essa mesma simplicidade de sintaxe e semântica que é responsável pelo fardo e pela liberdade suportados por todos os programadores Lisp. Nenhum programa Lisp de qualquer tamanho além de algumas linhas pode ser escrito sem estar saturado com funções discricionárias. Inventar e ajustar; ter ajustes e reinventar! Brindamos ao programador Lisp que escreve seus pensamentos entre parênteses.
Alan J. Perlis - New Haven, Connecticut