2 – Histórico

Propaganda
Linguagem Lisp
Everton Luís Berz¹, Diogo Santinon¹
¹ Faculdades de Informática de Taquara - Faculdades de Taquara (FACCAT)
{everton, diogo}@faccat.br
Resumo. Este artigo descreve um histórico, características e aplicabilidade da linguagem
LISP (List Processing). No final do artigo é mostrado um exemplo de programa em LISP.
1. Histórico
A linguagem LISP foi inspirada pelo Cálculo Lambda, um formalismo desenvolvido nos
anos 30 por Alonzo Church. O Cálculo Lambda pode ser considerado como uma linguagem
de programação abstrata, onde o conceito de Computação, isto é, as maneiras como funções
podem ser combinadas para formar outras funções, aparecem em toda sua generalidade e de
uma forma pura, sem complicações sintáticas.
A principal característica do Cálculo Lambda é tratar funções como entidades que
podem ser, como um dado qualquer, utilizadas como argumentos retornadas como valores
de outras funções. Esta característica é preservada na linguagem LISP onde dados e funções
tem exatamente o mesmo status.
Podemos observar através disto que as m-expression (expressões-M), M significa
Metalangue (meta linguagem) são também expressões lambda. São três os benefícios do
Cálculo Lambda:
 Simplicidade: só existem três tipos de expressões (s-expressões, átomos e listas);
 Completo: não existe função que não possa ser representada;
 Generalidade: funções podem ser passadas como argumentos, simplificadas,
comparadas, etc.
O Cálculo Lambda é completo, mínimo e simples. Sua sintaxe é enxuta, contendo
apenas três tipos de expressões, assim como sua semântica, que também é de fácil
compreensão. A recursão é permitida livremente.
Lisp é uma família de linguagens que possuem uma longa história; as primeiras
idéias-chave para a linguagem foram desenvolvidas por John McCarthy em 1956, durante
um projeto de pesquisa em inteligência artificial. A motivação de McCarthy surgiu da idéia
de desenvolver uma linguagem algébrica para processamento de listas para trabalho em IA
(inteligência artificial). Esforços para a implementação de seus primeiros dialetos foram
empreendidos no IBM 704, IBM 7090, DEC PDP-1, DEC PDP-6 e DEC PDP-10.
O dialeto principal entre 1960 e 1965 foi o Lisp 1.5. No início dos anos 70, houve
outros dois dialetos predominantes, desenvolvidos através de esforços anteriores: MacLisp
e Interlisp.
O MacLisp aperfeiçoou a noção de variáveis especiais e o suporte a erros. Também
introduziu o conceito com número variável de argumentos, macros, arrays, cálculos
rápidos, além de enfatizar a velocidade de execução.
O Interlisp introduziu muitas idéias na metodologia no ambiente de execução. Uma
de suas idéias que influenciou os dialetos mais recentes foi à construção que mais tarde
inspiraria a macro Loop, implementada por Warren Teitelman.
Apesar das primeiras implementações do Lisp terem sido feitas nos IBM 704 e
7090, trabalhos posteriores concentravam-se nos DEC PDP-6 e PDP-10, este último sendo
o baluarte do Lisp e das pesquisas em IA (inteligência artificial) em lugares como o MIT
(Massachussets Institute of Tecnology) e as Universidades de Stanford e Carnegie-Mellon
até metade dos anos 70. O computador PDP-10 e seu antecessor, o PDP-6 eram por
definição, especialmente adequados para o Lisp, devido a possuírem palavras de 36 bits e
endereços de 18 bits. Esta arquitetura permitia um registro de um conscell (par pontuado)
em uma única palavra de memória, em instruções simples extraiam o seu car e cdr. Esses
computadores possuíam também poderosas instruções de pilha, que proporcionavam rápida
chamada às funções; porém suas limitações em 1973 eram evidentes: suportavam um
pequeno número de pesquisadores utilizando o Lisp e seu endereçamento em 18 bits
limitava o espaço dos programas. Uma resposta para o problema de endereçamento foi o
desenvolvimento do "Lisp Machine", um computador dedicado especialmente à tarefa de
trabalhar com a linguagem. Outra solução foi à utilização de computadores de uso geral
com maior capacidade de endereçamento, como o DEC VAX e o S1 Mark IIA.
Ao final dos anos 70, um grupo de pesquisadores do MIT (Massachussets Institute
of Tecnology) deram início ao projeto NIL (New Implementation of Lisp) para o DEC
VAX. Um dos êxitos do programa foi consertar muito dos já históricos, porém irritantes
"bugs" que a linguagem apresentava. Simultaneamente, pesquisadores da Universidade de
Stanford começaram o desenvolvimento de um dialeto específico para o supercomputador
S1 Mark IIA, dialeto conhecido como S1 Lisp, que possuía a característica de não ser
totalmente funcional.
Esforços de padronização da linguagem iniciaram-se em 1969, quando Anthony
Hearn e Martin Griss da Universidade de Utah definiram o Standard Lisp, um subconjunto
do Lisp 1.5 e de outros dialetos. Nos anos seguintes, o mesmo grupo desenvolveu uma
nova implementação conhecida como PSL (Portable Standard Lisp), que chegou a ser
utilizado até meados da década de 80, devido a sua grande portabilidade.
Durante a segunda metade dos anos 70, um importante avanço ocorreu: foi à
implementação do Scheme Lisp, projetado por Gerald Sussman e Guy L. Steele Jr., o qual
consiste em um dialeto relativamente simples, cujo projeto trouxe de volta alguns dos
conceitos originais da semântica da linguagem.
No final dos anos 70, a programação orientada a objetos trouxe a sua contribuição.
Inspirados em alguns conceitos do Small Talk, pesquisadores do MIT (Massachussets
Institute of Tecnology) desenvolveram o Flavors, primeiro Lisp com orientação a objetos.
A própria Xerox também desenvolveu o seu dialeto Lisp: O LOOPS (Lisp Object-Oriented
Programming System).
A facilidade de utilização, adaptação e extensão da linguagem Lisp, aliada à sua
origem acadêmica, fez com que surgissem dezenas de versões diferentes: FranzLisp,
ZetaLisp, LeLisp, MacLisp, InterLisp, Scheme, T, Nil, XLisp, AutoLisp, etc, para nomear
apenas as mais relevantes. Esta variedade de dialetos começou a tornar difícil a livre
comunicação entre os membros da comunidade Lisp. Para obviar este problema, em Abril
de 1981 os grupos de pesquisa Symbolics, NIL, S1 e SPICE reuniram-se para criar um
Standard denominado Common Lisp com o objetivo de facilitar a troca de idéias (e
programas).
Citado por Antônio Menezes Leitão, “sendo a linguagem Common Lisp o herdeiro
legítimo de todas as outras, ela deve suportar a maioria das capacidades que estas possuem.
Como é lógico isto impede a estabilização da linguagem, que ainda não parou de evoluir,
sendo ampliada de tempos a tempos para incorporar novos (e velhos) paradigmas de
programação. Felizmente, essa ampliação evita (na medida em que isso é possível) alterar
funcionalidades das versões anteriores e assim um programa Common Lisp tem a garantia
de funcionar independentemente do estado atual da linguagem. O programa pode não estar
tecnologicamente atual, mas estará sempre funcionalmente atual“.
Citado por João Bosco da Mata Alves, “LISP tornou uma das principais linguagens
de Inteligência Artificial”.
2. Paradigmas de Programação
Principalmente devido ao seu longo tempo de existência, LISP é uma linguagem funcional
atípica, pois também suporta muitas das estruturas das linguagens imperativas, estruturas
essas ausentes nas modernas linguagens funcionais.
3. Características Técnicas
A linguagem LISP é interpretada, onde o usuário digita expressões em uma linguagem
formal definida e recebe de volta a avaliação de sua expressão. Deste ponto de vista
podemos pensar no LISP como uma calculadora, que ao invés de avaliar expressões
aritméticas avalia expressões simbólicas, chamadas de expressões. Cada programa em
LISP, é, portanto, uma expressão. As expressões são de tamanho indefinido e tem uma
estrutura de árvore binária.
A estrutura de utilização da memória disponível é na forma de listas, pois livra o
programador da necessidade de alocar espaços diferentes para o programa e para os dados,
fazendo com que os dados e os programas sejam homogêneos, característica única da
linguagem LISP.
Suas principais características são:
 Tipos de dados: átomo e a lista. É com apenas esses dois tipos de dados que se
constroem as expressões-S, as estruturas basilares de LISP.
 Fraca Tipagem: LISP, em relação a outras linguagens funcionais mais recentes, é
fracamente tipado, o que causa complicações, já que operações que acessam as suas
estruturas de dados são tratadas como funções.
 Funções de ordem elevada: Linguagens funcionais tipicamente suportam funções de
ordem elevada (exemplo: função de uma função de uma função de uma...).
 Avaliação Ociosa: É o que ocorre quando uma função aninhada executa uma
computação desnecessária para a avaliação da função que a chama, aumentando o
tempo de execução.
 Concorrência (multitarefa): A concorrência nas linguagens imperativas tradicionais
é relativamente complexa; o programador é o responsável pela sincronização de
todas as tarefas (a multitarefa no paradigma procedural é tão sofisticada quanto um
GOTO). Em contraste, as linguagens funcionais intrinsecamente nos oferecem
oportunidades para a concorrência: A partir do momento em que uma função tem
mais de um parâmetro, estes parâmetros devem em princípio ser avaliados
simultaneamente (note que os parâmetros seriam as funções correspondentes às
tarefas a serem executadas); A partir deste ponto, a responsabilidade pela
sincronização das tarefas passa do programador para o compilador (as modernas
linguagens funcionais orientadas a multitarefa dispõe de mecanismos através dos
quais o programador pode guiar o compilador). Todavia, as linguagens funcionais
orientadas a multitarefa permitem ao programador trabalhar em um nível muito
mais elevado do que as linguagens imperativas destinadas a este mesmo fim.
el de abstração, especialmente quando as funções são utilizadas,
suprimindo muitos detalhes da programação e minimizando a probabilidade da
ocorrência de muitas classes de erros;
programas
avaliações nas mais diferentes ordens. Esta característica de avaliação independente
da ordem torna as linguagens funcionais as mais indicadas para a programação de
computadores maciçamente paralelos;
na os programas funcionais muito mais
simples para provas e análises matemáticas do que os programas procedurais.
E como desvantagem, destacamos:
(ex. contas de banco) ou muitas atividades seqüenciais são muitas vezes mais fáceis
de se trabalhar com programas procedurais ou programas orientados a objeto.
O Common Lisp permite várias representações diferentes de números. Estas
representações podem ser divididas em 4 tipos: hexadecimais, octais, binários e decimais.
Estes últimos podem ser divididos em 4 categorias: inteiros, racionais, ponto flutuante e
complexos.
Funções em LISP:
Chamada de função:
(+ 3 2 5);
=10
3.1 Avaliação
Em Lisp, (+) é uma função, e uma expressão como (+ 2 3) é uma chamada de função
envolvendo dois argumentos. Quando Lisp avalia uma chamada de função, ele o faz em
duas etapas.
Primeiramente os argumentos são avaliados, da esquerda para a direita. Neste
contexto, cada argumento se "auto–avalia", e assim os valores dos argumentos são 2 e 3,
respectivamente; finalmente, os valores dos argumentos são passados a função designada
pelo operador. Neste caso, é a função +, que retorna 5.
; ==>Indica que é uma linha de comentário.
(setf total 4) ==> seta a variável (total) com um valor (4);
read – esta função não recebe nenhum argumento. O próprio comando não avalia sua
entrada, apenas recebe os dados que o usuário digitar no teclado (sempre seguidos de
<enter>). Geralmente vem combinado com outras funções: Ex:
(setf total (read))
(define x 0) ==> seta x como 0;
(display “Olá mundo”) ==> Escreve o conteúdo que esta dentro das aspas na saída padrão,
o comando print é idêntico.
(quote atomo1 atomo2 ... ) ==> Retorna um átomo (quando tem somente 1 argumento) ou
uma lista a partir dos átomos. Esta função normalmente tem uma abreviação utilizando-se
do apóstrofe. (quote jose silva) <==> '(jose silva)
(car lista) ==> Retorna o primeiro elemento da lista. Ex: (car '(jose silva)) retorna jose. Nas
implementações mais recentes o LISP foi padronizado pela ISO e esta função foi duplicada
como nome de first.
(cdr lista) ==> Retorna a lista sem o primeiro elemento. Ex: (cdr '(jose da silva)) retorna
(da silva). Novo nome desta função rest.
(cons atomo lista) ==> Adiciona átomo ao início da lista. Ex: (cons 'jose '(da silva)) retorna
(jose da silva).
Funções matemáticas
+ --> Adição
- --> Subtração
* --> Multiplicação
/ --> Divisão
( sqrt 4 )  2.0 ==> função q retorna o quadrado no número
( expt 2 10 )  1024 ==> função exponencial
4. Aplicabilidade da LP
Lisp é uma linguagem madura, concebida atenciosamente, altamente portável, linguagem
de força industrial na qual desenvolvedores sérios em todo o mundo contam para:
ara fazer coisas do dia a dia.
outra linguagem.
elas que necessitam de mudanças
após a etapa inicial.
A linguagem teve um grande sucesso em software do ramo de negócios, engenharia,
processamento de documentos, hipermídia (incluindo a Web), matemática, gráficos e
animação, inteligência artificial e processamento de linguagem natural. Uma das grandes
vantagens de Lisp é que ela trata o programa como dado, possibilitando assim um programa
inteiro ser dado como entrada de um outro, coisa que não acontece em outras linguagens
como C e Pascal. E usada algumas vezes para definir todos os aspectos de uma aplicação,
ou apenas o motor de processamento interno, ou apenas a interface do usuário; e ainda é
usada com rotina para prover linguagens de comando interativas, linguagens de macro ou
script e linguagens extensoras de sistemas comerciais.
5. Exemplo de Programa
;Programa de calculo de media das notas e situação final de alunos da FACCAT
; (http://www.faccat.br)
; Pode ser baixado neste endereco: http://fit.faccat.br/~everton/lp/media.lsp
; Para rodar digite no console: clisp media.lsp
;
;** Funcao de validacao da nota
*******************************************************************
(defun validanota (nota)
(setf NOTAMAXIMA 10)
(setf NOTAMINIMA 0)
;
(setf retorno T)
;
(if (or (> nota NOTAMAXIMA)
(< nota NOTAMINIMA))
(progn
(princ "Nota inválida. A nota deve estar entre ")
(princ NOTAMINIMA)
(princ " e ")
(princ NOTAMAXIMA)
(terpri)
(setf retorno nil)
)
)
retorno
)
;** Inicio
********************************************************************
(setf MEDIASEMESTREAPROVACAO 8)
(setf MEDIAFINALAPROVACAO 6)
;
(setf g1 -1)
(setf g2 -1)
(setf sg1 -1)
(setf sg2 -1)
(setf ms -1)
(setf ex -1)
(setf mf -1)
(setf fazerSG 'sim)
(setf qualSG 0)
(setf fazerEX 'sim)
;
(terpri)
(princ "Aplicação iniciada...")
(terpri)
(terpri)
(princ "Sistema de cálculo de média FACCAT")
(terpri)
(terpri)
(terpri)
;******************** G1
(loop
(progn
(princ "Entre com a nota do G1: ")
(setf g1 (float (read)))
(if (validanota g1)
(return)
)
)
)
(terpri)
;******************** G2
(loop
(progn
(princ "Entre com a nota do G2: ")
(setf g2 (float (read)))
(if (validanota g2)
(return)
)
)
)
(terpri)
;************************ EXIBE MEDIA DO SEMESTRE
(setf ms (/ (+ g1 g2) 2))
(princ "Média do Semestre: ")
(princ ms)
(terpri)
;******************** SG
(if (>= (/ (+ g1 g2) 2) MEDIASEMESTREAPROVACAO)
(progn
(princ "Voce ja está aprovado. Deseja fazer substituição mesmo assim (sim|nao)? ")
(setf fazerSG (read))
(terpri)
)
)
;
(if (equal fazerSG 'sim)
(progn
(princ "Qual substituição deseja fazer (1|2|nenhum) ? ")
(setf qualSG (read))
(terpri)
;******************** SG1
(if (equal qualSG 1)
(loop
(progn
(princ "Entre com a nota da subst. do G1: ")
(setf sg1 (float (read)))
(if (validanota sg1)
(return)
)
)
)
)
;******************** SG2
(if (equal qualSG 2)
(loop
(progn
(princ "Entre com a nota da subst. do G2: ")
(setf sg2 (float (read)))
(if (validanota sg2)
(return)
)
)
)
)
)
)
;************************ EXIBE MEDIA DO SEMESTRE
(if (= sg1 -1)
(setf sg1 g1)
)
(if (= sg2 -1)
(setf sg2 g2)
)
;deve ficar a nota mais alta
(if (< sg1 g1)
(setf sg1 g1)
)
(if (< sg2 g2)
(setf sg2 g2)
)
;
(setf ms (/ (+ sg1 sg2) 2))
(princ "Média do Semestre: ")
(princ ms)
(terpri)
(terpri)
;************************ EXAME
(if (>= (/ (+ sg1 sg2) 2) MEDIASEMESTREAPROVACAO)
(progn
(princ "Voce ja está aprovado. Deseja fazer exame mesmo assim (sim|nao)? ")
(setf fazerEX (read))
(terpri)
)
)
;
(if (equal fazerEX 'sim)
(loop
(progn
(princ "Entre com a nota do exame: ")
(setf ex (float (read)))
(if (validanota ex)
(return)
)
)
)
)
;************************ CALCULA MEDIA FINAL
(if (= ex -1)
(setf mf ms)
(setf mf (/ (+ ms ex) 2))
)
(princ "Média final: ")
(princ mf)
(terpri)
;************************ EXIBE RESULTADO
(princ "Situação: ")
(if (>= mf MEDIAFINALAPROVACAO)
(princ "Aprovado")
(princ "Reprovado")
)
(terpri)
(terpri)
;
(princ "Sistema encerrado.")
(terpri)
6. Bibliografia
http://pt.wikipedia.org/wiki/Lisp
http://www.dca.fee.unicamp.br/courses/EA072/lisp9596/Lisp9596.html
http://www.cadblocos.arq.br/lisp.html
http://www.gia.ist.utl.pt/Lisp9596/Lisp9596.html
http://edsonjr.prof.unopar.br/cad_menu/lisp.html
http://www.portaldaprogramacao.com/index_linguagem.asp?c=50
http://minerva.ufpel.edu.br/~marhinz/avaliador.htm
Software CLEAN esta disponivel via ftp: ftp://ftp.cs.kun.nl/pub/Clean
http://www.milenio.com.br/grottoli/Academicos/introducao_lisp.zip
Download