Escolar Documentos
Profissional Documentos
Cultura Documentos
Joo Meidanis
Contedo
1 Introduo
1.1 1.2 1.3 1.4 Calculando derivadas simblicas . . . . . . . . . . . . . . . . . O psiquiatra . . . . . . . . . . . . . . . . . . . . . . . . . . . . MYCIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
5 5 6 7
Interpretador
2 Elementos da linguagem
2.1 2.2 2.3 2.4 2.5 2.6 2.7 Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nmeros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Smbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pares-com-ponto . . . . . . . . . . . . . . . . . . . . . . . . .
11
11 11 12 12 13 15 15
Coleta de lixo . . . . . . . . . . . . . . . . . . . . . . . . . . .
3 Estrutura da linguagem
17
17 18 20
4 Smbolos
4.1 4.2 4.3 Avaliao e valores de um smbolo . . . . . . . . . . . . . . . . Atribuindo valores a smbolos . . . . . . . . . . . . . . . . . .
22
22 23 24
Inibindo a avaliao . . . . . . . . . . . . . . . . . . . . . . . .
5 Recurso
5.1 5.2 O mtodo do quadrado . . . . . . . . . . . . . . . . . . . . . Recurso e laos . . . . . . . . . . . . . . . . . . . . . . . . . .
26
26 29
6 Aritmtica
6.1 6.2 Funes bsicas . . . . . . . . . . . . . . . . . . . . . . . . . . Funes mais sosticadas . . . . . . . . . . . . . . . . . . . . .
31
31 33
34 36
IF
. . . . . . . . . . . . . . . . . . . . . . . .
36 37 38
COND
. . . . . . . . . . . . . . . . . . . . . . . . . . .
Predicados . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
44 47
47 48 48 49
12 Arrays e Loops
12.1 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1.1 Criando arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
50 50 50 51
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Captulo 1 Introduo
LISP vem de list processing. John McCarthy criou LISP em 1960 [1]. sustentabilidade da vida humana na Terra. LISP uma linguagem to antiga que na poca em que foi criada os computadores S USAVAM LETRAS MAISCULAS. Quando vieram as letras minsculas, foi adotada a conveno de que em LISP uma letra minscula ou maiscula a mesma coisa. Portanto, as palavras 'SEN', 'sen' e 'SeN' em LISP so todas equivalentes. O padro Common Lisp, consolidado em 1990, veio unir os vrios dialetos de LISP existentes na poca para formar uma linguagem bastante bem especicada. Usaremos o livro Hoje em dia ele trabalha com
2a. edio, de
Guy Steele, onde este padro detalhado com grande cuidado, como referncia principal sobre LISP neste curso [3]. Site na internet (um de vrios):
http://www.supelec.fr/docs/cltl/cltl2.html
Algumas aplicaes famosas escritas em LISP seguem.
(+ (* X X) (* 3 X)).
Se for denida uma funo chamada pedir:
(+ (* 2 x) 3)
ou seja,
2x + 3.
1.2 O psiquiatra
ELIZA, que pretendia simular um psiquatra, foi talvez o primeiro programa de computador a passar o Teste de Turing. Foi escrito por Joseph Weizenbaum em 1966 [4].
Embora o
autor em seu artigo original tenha dito que o programa pode ser portado para outras lnguas (inclusive mencionando que j naquele momento existia uma verso em alemo), as verses mais difundidas so em ingls. O programa utiliza uma estratgia de psiquiatra Rogeriano, na qual o paciente sempre estimulado a falar, elaborando sobre o que j disse. Eis um fragmento de conversao:
Men are all alike. IN WHAT WAY? They're always bugging us about something or other. CAN YOU THINK OF A SPECIFIC EXAMPLE? Well, my boyfriend made me come here. YOUR BOYFRIEND MADE YOU COME HERE
E por a vai. As frases em maisculas so as respostas do programa. Existe uma verso dentro do Emacs:
M-x doctor.
Este programa causou tanta sensao, e ainda causa! Recentemente, algum acoplou-o a um AOL Instant Messenger e deixou que pessoas ao acaso se plugassem para falar com ele. Os resultados foram surpreendentes! Conra na Internet.
1.3 MYCIN
MYCIN, um sistema pioneiro para diagnsticos mdicos, foi um dos precursores dos sistemas especialistas [2]. MYCIN representa seu conhecimento sobre os sintomas e possveis diagnsticos como um conjunto de regras da seguinte forma:
E suspeita-se que a porta de entrada o trato gastro-intestinal ENTO h evidncia sugerindo (0.7) que a infeco bacteride.
As regras so na verdade escritas como expresses LISP. O valor 0.7 uma estimativa de que a concluso seja correta dadas as evidncias. desta regra para chegar estimativa de correo da concluso. Se as evidncias so tambm incertas, as suas estimativas sero combinadas com as
1.4 Interpretador
A maneira padro de interao com uma implementao de Common Lisp atravs de um lao ler-avaliar-imprimir (
read-eval-print loop ):
o sistema
repetidamente l uma expresso a partir de uma fonte de entrada de dados (geralmente o teclado ou um arquivo), avalia a expresso, e imprime o(s) valor(es) em um destino de sada (geralmente a tela ou um arquivo). Expresses so tambm chamadas de formas, especialmente quando so destinadas avaliao. Uma expresso pode ser simplesmente um smbolo, e neste caso o seu valor o valor como dado do smbolo. Quando uma lista avaliada (exceto nos casos de macros e formas especiais), supe-se que seja uma chamada de funo. O primeiro elemento da lista tomado como sendo o nome da funo. Todos os outros elementos da lista so tratados como expresses a serem avaliadas tambm; um valor obtido de cada uma, e estes valores se tornam os argumentos da funo. A funo ento aplicada aos argumentos, resultando em um ou mais valores (exceto nos casos de retornos no locais). Se e quando a funo retornar, os valores retornados tornam-se os valores da lista avaliada. Por exemplo, considere a avaliao da expresso (+ 3 (* 4 5)). O smbolo + denota a funo de adio, que no uma macro nem uma forma especial. Portanto as duas expresses 3 e (* 4 5) so avaliadas para produzir argumentos. A expresso 3 resulta em 3, e a expresso (* 4 5) uma chamada de funo (a funo de multiplicao). Portanto as formas 4 e 5 so avaliadas, produzindo os argumentos 4 e 5 para a multiplicao. A funo de multiplicao calcula o nmero 20 e retorna-o. Os valores 3 e 20 so ento
dados como argumentos funo de adio, que calcula e retorna o nmero 23. Portanto indicamos
Usaremos CMUCL, a implementao do Common Lisp feita pela Carnegie Mellon University, EUA. Onde pegar: faa
download
http://www.cons.org/cmucl/credits.html.
Como instalar:
Se voc vai usar Windows, h vrios outros pacotes na internet. Mas cuidado: antes de entregar qualquer projeto da disciplina, teste seu cdigo no CMUCL! Em geral, as modicaes sero poucas ou menhuma, especialemnte se voc usar construes portteis. S sero aceitos projetos que rodem em CMUCL. Como usar (bsico):
entrar: sair:
usar com arquivo: escreva um arquivo de texto simples com as expresses a avaliar, d a ele extenso
arquivo.lsp
seguidas de
lisp <
ENTER
**
***
preparar:
inferior-lisp-program "lisp"
deve ter valor igual ao comando usado para chamar o interpretador. Se voc estiver usando o CMUCL, este valor iniciar:
M-x run-lisp
teragir com o interpretador. como se fosse uma shell interna ao Emacs. sair:
(quit) lisp-mode
usar com arquivo: se voc estiver editando um arquivo Emacs usar tao e balanceamento de parnteses, por exemplo
.lsp,
C-x C-e
.lsp,
M-x describe-bindings
Uma grande vantagem de usar o editor Emacs que ele balanceia os parnteses para voc. E cuida tambm da indentao.
prev que seja compiladas funes ou arquivos LISP, para rodarem mais
deriv,
(compile 'deriv).
Para compilar um arquivo
deriv.lsp,
(compile-file "deriv.lsp").
Erros: tecle
Depurao: para depurar seus programas, importante saber que existe um mecanismo de trace:
(trace deriv).
deriv
imprime o valor dos argumentos passados funo, e cada retorno imprime o valor retornado. Para cancelar o trace, use tracear vrias funes ao mesmo tempo:
Exerccios
1. Procure na internet uma verso do programa que calcula derivadas em LISP e use-o para calcular as derivadas das funes dadas como exemplo acima. 2. Converse um pouco com o psiquiatra do Emacs. Traga seus dilogos para a classe.
3. Procure na Internet a experincia feita com o psiquiatra e usurios ao acaso do AOL. Traga alguns dilogos interessantes para a classe. 4. Carregue o interpretador e pea para avaliar:
(+ 1 (* 3 4)).
Avalie
10
2.2 Nmeros
Nmeros: inteiros, razes, ponto utuante, complexos. Inteiros: xnum e bignum.
11
real
em Pascal, ou
float
em C e Java.
i,
etc.
2.3 Smbolos
Smbolos: sero tratados no Captulo 4. Por enquanto, vamos considerlos como seqncias de caracteres que podem incluir letras, nmeros e sinais especiais, exceto brancos e parnteses, e que no possam ser confundidos com nmeros. Alm disso, no devem conter apenas pontos. Exemplos de nomes vlidos para smbolos:
+1 ..
2.4 Pares-com-ponto
Pares-com-ponto, ou conses: so estruturas, ou registros, com dois componentes:
car
cdr.
12
(A . B).
Listas: uma lista denida como sendo ou bem a lista vazia ou bem um cons cujo cdr uma lista. O smbolo expresso
()
sinnima de
NIL.
NIL
Listas so denotadas escrevendo seus elementos na ordem, separados por espaos em branco (caracteres: espao, tab ou newline) e cercados por parnteses. Um cons cujo segundo elemento no uma lista denotado de forma semelhante, exceto h um ponto . (cercado de espao em branco) precedendo o ltimo cdr. Exemplo:
(a . 4)
13
"ca"
10.0
( ( A . 1 ) . ( "ca" . ( x . 10.0 ) ) ).
NIL
(A . NIL),
ou simplesmente
(A).
NIL
A
Figura 2.4: Representao grca de mas de expressar ponteiros a
NIL.
( A ( A B ) E ).
14
sinnimo de CAR. A funo CDR retorna o segundo componente de um cons. REST um sinnimo de CDR. Se CAR ou CDR forem aplicadas a o resultado um cons ou
(),
B) E)) => A 1).("ca".(x . 10.0)))) => (A . 1) B) E)) => ((A B) E) 1).("ca".(x . 10.0)))) => (("ca" x . 10.0)) => indica o resultado da avaliao de uma expres-
A funo CONS recebe dois argumentos e retorna uma nova caixa contendo estes argumentos como componentes, na ordem dada. No h sinnimos para CONS. Exemplos:
garbage collection ).
Neste sistema, o
programador no precisa se preocupar em alocar ou desalocar memria explicitamente. Ao invs disso, o prprio interpretador da linguagem se encarrega de alocar e desalocar memria quando necessrio. A alocao de memria ocorre sempre que CONS chamada, direta ou indiretamente. Quanto desalocao, ela ocorre quando necessrio alocar mais memria mas acabou
15
a memria do sistema. Neste momento o interpretador sai coletando lixo, que so caixas que no esto sendo mais apontadas por nenhuma estrutura do sistema, e que podem portanto ser liberadas. Por exemplo, na avaliao da expresso:
Exerccios
1. Quais dos seguintes smbolos so vlidos: 2. LISP sabe mexer com fraes: avalie
(+ 2/3 4/5).
21000
usando a expresso
(expt 2 1000).
4. Quais das seguintes expresses denotam listas:
. (B . C)).
5. Desenhe a representao grca de:
(), ( (A . B) C), (A
6. Calcule o CAR e o CDR das expresses dos dois ltimos exerccios. 7. Para formar
(A B C) a partir de tomos necessrio fazer: (cons 'a (cons 'b (cons 'c ()))). Monte expresses semlhantes para os
conses dos exerccios 4 e 5.
16
com efeitos colaterais so mais difcies de entender e manter, por isso devem ser evitadas. Nesta disciplina, daremos nfase programo em LISP puro, sem efeitos colaterais, ou reduzindo-os ao mnimo.
17
Antes, porm, vamos relembrar como efetuar operaes aritmticas em LISP. As quatro operaes bsicas da aritmtica so implementadas pelas funes pr-denidas indicadas por
+, -, *, /
e a notao prexa.
ax2 + bx + c:
3.2 Condicionais
Para prosseguir no nosso estudo de LISP, precisamos conhecer os condicionais, que permitem seleo de uxos alternativos de cdigo. mais usados so IF e COND. A forma especial IF recebe trs argumentos. Aps a avaliao do primeiro, apenas um dos outros dois avaliado. Se o valor do primeiro argumento seja diferente de NIL, o segundo argumento escolhido; caso contrrio, o terceiro argumento escolhido. Em qualquer caso, o argumento escolhido avaliado e tem seu valor retornado pela forma IF. Para quem est acostumado com programao imperativa, leva um tempo para se acostumar com esta maneira nova de lidar com um IF. Ele parece mais uma funo agora, e no mais um comando. Observe tambm que LISP no tem um tipo booleano. Para ns de verdadeiro ou falso, podemos dizer que NIL falso, e todo o resto verdadeiro. Vejamos alguns exemplos. nmeros: A seguinte funo retorna o maior entre dois Em LISP, os
18
>.
if.
case
(ou
switch
19
(defun maior3 (x y z) (cond ((and (>= x y) (>= x z)) x) ((and (>= y x) (>= y z)) y) ((and (>= z x) (>= z y)) z) ) )
Observe o uso de uma nova funo: Existe tambm
or.
x.
que faamos este tipo de construo. Por exemplo, ao calcular as razes de uma equao do segundo grau, precisaremos do discriminante. A funo a seguir recebe os coecientes de uma equao do segundo grau e retorna uma de suas razes.
(defun raiz (a b c) (let ((disc (discr a b c))) (/ (+) (- b) (sqrt disc)) (* 2 a)) )
Observe o uso de
sqrt,
20
Mais de uma varivel local pode ser denida no mesmo bloco LET. Existe tambm uma variante do LET, chamada LET, que permite que cada varivel dependa da anterior. da equao: A funo a seguir utiliza este recurso e tambm a funo pr-denida LIST para a formao de uma lista com as duas razes
(defun raizes (a b c) (let* ( (disc (discr a b c)) (r1 (/ (+ (- b) (sqrt disc)) (* 2 a))) (r2 (/ (- (- b) (sqrt disc)) (* 2 a))) ) (list r1 r2) ) )
A sintaxe completa das formas LET pode ser encontrada no manual online.
Exerccios
1. Escreva uma funo para calcular a mdia entre dois nmeros. 2. Modique a funo que retorna as razes de uma equao do segundo grau para que retorne as partes real e imaginria das razes, no caso de elas serem complexas. Suponha que os coecientes sejam reais.
21
Captulo 4 Smbolos
Smbolos so objetos em LISP que aparecem em vrios contextos: nomes
name ou pname ).
string, e vice-versa. Smbolos no precisam ser explicitamente criados. A primeira vez que o
property list
ou
plist ).
Duas
Uma expresso em LISP um tomo ou uma lista. Se for um tomo, temos trs possibilidades: nmero, string ou smbolo. A avaliao de um nmero resulta no prprio nmero, e o mesmo ocorre com strings. Para um smbolo, a coisa diferente. A avaliao de um smbolo resulta no seu valor como dado. Caso o smbolo no tenha valor como dado, ocorre um erro. Isto encerra a questo de avaliar tomos. Mas, e quanto a avaliar listas? Na
22
hora de avaliar, uma lista sempre vista como a chamada de uma funo. O primeiro elemento da lista o nome da funo e os elementos restantes so os argumentos. Para avaliar uma lista, LISP procura o valor como funo do primeiro elemento, depois avalia os argumentos, e nalmente aplica a funo nos valores dos argumentos. Por exemplo, ao avaliar a lista
(+ 1 2 3)
LISP busca o valor como funo do smbolo
+,
denida que soma nmeros. Depois, LISP avalia os argumentos, que no caso so nmeros e portanto correspondem a seus prprios valores. Finalmente, LISP aplica a funo pr-denida nos valores 1, 2 e 3, resultando em 6.
(setf x 8)
Observe que esta uma forma impura de modicar o valor como dado de um smbolo, pois resulta de um efeito colateral, e na guarda o valor anterior para se desfazer a ao, caso necessrio. Existem outras formas de modicar o valor como dado de um smbolo que so mais puras, ou seja, tem efeito temporrio, e o smbolo volta ao valor anterior ao nal de um certo processo. So elas: o bloco LET e a passagem de parmetros a uma funo. Note
23
que tanto o LET como a chamada de uma funo fazem uma atribuio de valores a certos smbolos, e esta atribuio desfeita aps o m do processo correspondente (m do bloco LET no primeiro caso; m da execuo da funo, no segundo caso). Mesmo assim, SETF bastante usado para variveis globais ou vetores. SETF muito til para armazenar expresses grandes para testar funes junto ao interpretador. No entanto, importante evitar seu uso indiscriminado, por exemplo, em simples traduo de construes imperativas (de Pascal, C ou Java) para LISP.
(quote a) => A '(cons 'a 'a) => (CONS (QUOTE A) (QUOTE A))
Existe tambm uma forma de especicar expresses quase constantes, isto , expresses nas quais grande parte constante exceto alguns pontos onde se deseja avaliao. O acento grave usado no lugar do apstrofe, e as sub-expresses que se deseja avaliar so precedidas de vrgula:
Exerccios
1. Suponha que foram denidos:
24
(car '((a b c d))) (cdr '((a b c d))) (car (cdr (car (cdr '((((a b) (c d)) (e f)) (g h)))))) (cons (car '(a b f)) (cons (cons 'c '(x)) nil))
25
Captulo 5 Recurso
Recurso ocorre quando uma funo chama a si prpria, direta ou indiretamente. Por exemplo, considere a seguinte denio de fatorial.
26
usar um argumento especco para determinar como o resultado da chamada recursiva deve ser trabalhado para obter o resultado a retornar. O mtodo tem este nome devido gura que desenhamos para tirar as concluses, que pode ser vista na Figura 5.1.
argumento
cdr f
cdr do argumento
Figura 5.1: O mtodo do quadrado. Comeamos escolhendo um argumento especco para o clculo da funo. Este argumento colocado no canto superior esquerdo do quadrado. A partir dele, traamos uma seta para a direita, que simboliza a aplicao da funo
aplicada
ao argumento. A seguir, descendo a partir do argumento escolhido, escrevemos o baixo simbolizando a aplicao da funo de
cdr
deste
cdr.
f,
levando ao valor
aplicada ao
cdr
e tentamos descobrir como que se obtm o valor no canto superior direito a partir do valor no canto inferior direito. a seta que est indicada por na gura. Vamos a um exemplo. Suponha que desejemos escrever a funo lista. Acompanhe pela Figura 5.2.
count
que
recebe um item e uma lista e conta o nmero de ocorrncias deste item na Em nossa denio usaremos o nome
my-count
LISP, a funo
count
27
a, (b a c d a f)
count
cdr count
a, (a c d a f)
count.
O resultado
count
a e a lista (b a c d a f).
cdr
ao ar-
rior da gura resulta em 2 tambm. Como fazemos para obter 2 a partir de 2? Neste caso, no necessrio fazer nada, porm, se o primeiro elemento da lista fosse igual a
a,
(defun my-count (item lista) (if (null lista) 0 (+ (my-count item (cdr lista)) (if (equal item (car lista)) 1 0)
28
my-sort,
utilizando
insertion sort.
Neste caso,
uma nova funo ter que ser criada. Isto normal em LISP. Acabamos tendo vrias funes pequenas em vez de uma grande. mais fcil de manter.
n.
Para transformar isto em recurso em LISP, as atribuies, que so impuras, se transformam em outra forma de colocar valores em variveis: chamadas de funo, onde os parmetros recebem valores. Para tal, precisamos que uma funo auxiliar cujos parmetros sejam as variveis locais prprio parmetro
soma
i,
alm do
da funo inicial.
(defun soma (n) (somaux n 0 1)) (defun somaux (n soma i) (if (> i n) soma (somaux n (+ soma i) (1+ i)) ) )
29
Loops transformados em funes recursivas assim resultam numa forma de recurso especial, chamada de recurso de rabo (
tail recursion ),
mais eci-
ente do que outras formas de recurso. Recurso de rabo ocorre quando o resultado das chamadas recursivas retornado sem modicao pela funo. Existem construes LISP para loops, que sero tratadas mais adiante.
Exerccios
1. Escreva a funo
last,
member,
suxo da lista a partir do ponto onde ocorre o item pela primeira vez nela, ou NIL caso o item no ocorra na lista. 3. Exemplo de lao para transformar em recurso: contar o nmero de positivos numa lista. 4. Combinao
tomados
m.
30
Captulo 6 Aritmtica
LISP possui um repertrio notvel de funes aritmticas. veremos algumas delas. Neste captulo
-, *, /) com 0, 1, 2, 3 ou mais
todos eles. Se houver zero argumentos, retorna 0 que o elemento neutro para a adio. A funo
h s um argumento: da ela retorna o oposto dele. um erro cham-la com zero argumentos. A funo
de todos eles. Se houver zero argumentos, retorna 1 que o elemento neutro para a multiplicao. A funo
31
um erro cham-la com zero argumentos. D erro tambm se houver s um argumento e ele for zero, ou se houver mais de um argumento e algum dos divisores for zero. Esta funo produz razes se os argumentos so inteiros mas o resultado no inteiro.
(+) => 0 (+ 3) => 3 (+ 3 5) => 8 (+ 3 5 6) => 14 (-) => ERRO (- 3) => -3 (- 3 5) => -2 (- 3 5 6) => -8 (*) => 1 (* 3) => 3 (* 3 5) => 15 (* 3 5 6) => 90 (/) => ERRO (/ 3) => 1/3 (/ 3 5) => 3/5 (/ 3 5 6) => 1/10
floor arredonda para baixo; ceiling arretruncate arredonda em direo ao zero; round arredonda
para o inteiro mais prximo, e escolhe o par se houver dois inteiros mais
1+
1-:
e
gcd
lcm:
quer de argumentos inteiros, positivos ou negativos, retornando sempre um nmero positivo ou nulo. Com zero argumentos, retornam os elementos neutros para as respectivas operaes: 0 e 1.
32
Funo
abs:
sqr, sqrt.
calcula calcula
exp, log,
ex ; expt,
calcula
xy .
sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh. H tambm a constante pi.
Funes trigonomtricas: Nmeros complexos; funo
Todas as fun-
es acima que faa sentido aplicar em complexos aceitam complexos e produzem as respostas corretas. Algumas delas no faz sentido aplicar em complexos: arredondar e truncar, por exemplo.
Exerccios
1. Abra um livro do ensino mdio sobre fraes e use LISP para resolver expresses complicadas envolvendo fraes. Conra as respostas com as do livro. 2. Faa o mesmo para nmeros complexos.
33
&optional. &rest
junta todos os argumentos
restantes numa lista e passa esta lista funo. PROGN implcito no corpo de uma funo.
Exerccios
1. Escreva uma funo que aceite argumentos opcionais. 2. Escreva uma funo
34
35
Captulo 8 Condicionais
Neste captulo veremos certas expresses condicionais que servem para testar condies que selecionaro uma entre vrias expresses a avaliar.
forma especial
seus argumentos, ao contrrio das funes. Embora qualquer valor diferente de NIL seja considerado verdadeiro, existe o valor especial T que geralmente usado quando uma funo precisa retornar um valor verdadeiro especco (por exemplo, as funes de comparao etc.).
<, >,
36
Os smbolos NIL e T so constantes em Common LISP. Seus valores so NIL e T, respectivamente, e no podem ser modicados.
cond
{(
onde as estelas indicam repetio zero ou mais vezes. Assim, a macro COND tem um nmero qualquer de zero ou mais sendo cada uma delas uma lista de formas (expresses a avaliar). Uma clusula consiste de um
conseqentes.
teste
seguido de
A avaliao de um COND processa as clusulas da primeira ltima. Para cada clusula, o teste avaliado. Se o resultado NIL, o processamento passa para a prxima clusula. Caso contrrio, cada um dos conseqentes desta clusula availado e o valor do ltimo retornado pelo COND. Se no houver conseqentes, o valor do teste (que necessariamente diferente de NIL) retornado. Se as clusulas acabarem sem que nenhum teste seja verdadeiro, o valor retornado pelo COND NIL. comum colocar-se T como teste da ltima clusula, para evitar que isto acontea. A macro OR recebe zero ou mais argumentos e fornece uma espcie de ou lgico. Porm, ao invs de retornar somente T ou NIL, a forma OR retorna algo que pode ser mais til em determinadas situaes. Especicamente, OR avalia os argumentos da esquerda para a direita. Se
algum deles der verdadeiro, OR retorna este valor e no availa os demais. Se nenhum der verdadeiro, OR retorna NIL. A forma especial OR retorna portanto o valor do primeiro argumento que for diferente de NIL, no avaliando os demais.
37
A macro AND funciona de maneira similar: ela avalia os argumentos um a um, pra e retorna NIL ao achar o primeiro cujo valor seja NIL, e retorna o valor do ltimo se todos forem diferentes de NIL. Um caso especial o de zero argumentos, quando retorna T. Note que OR a AND foram denidos de tal forma que podem prefeitamente ser usados como funes booleanas. Alm disto existe a funo NOT, que retorna T se o argumento NIl e retorna NIL caso contrrio.
8.3 Predicados
Predicados so funes LISP que retornam um valor booleano. Alguns dos predicados mais importantes: com-ponto), lista, e nmero.
Eles
Exerccios
1. Quais das seguintes funes tm comportamento igual quando aplicadas a um nico argumento:
38
my-
para que,
(defun my-nth (indice lista) (if (= indice 0) (car lista) (my-nth (1- indice) (cdr lista)) ) )
elt lista indice: mesma coisa, s que a ordem dos argumentos trocada. last lista: retorna uma lista com o ltimo elemento da lista dada. Se a lista dada for vazia, retorna NIL. Observe que esta funo no retorna o ltimo elemento, mas a ltima caixa. Porm, se for desejado o ltimo elemento,
39
basta aplicar CAR ao resultado desta funo. Foi feito desta forma para poder distingir uma lista vazia de uma lista tendo NIL como ltimo elemento.
(defun my-last (lista) (if (null lista) () (if (null (cdr lista)) lista (my-last (cdr lista)) ) ) )
caar, cdar, etc. (at 6 letras a e c no meio, entre c e r): retornam a composio de at 6 aplicaes de CAR e CDR. Por exemplo:
(defun my-length (lista) (if (null lista) 0 (1+ (my-length (cdr lista))) ) )
member item lista: se item pertence lista, retorna a parte nal da lista comeando na primeira ocorrncia de item. pertence a uma lista. Se item no pertence lista, retorna NIL. Pode ser usado como predicado para saber se um certo item
(defun my-member (item lista) (cond ((null lista) nil) ((equal item (car lista)) lista) (t (my-member item (cdr lista)))
40
reverse lista: retorna uma lista com os elementos em ordem inversa relativa ordem dada.
(defun my-reverse (lista) (my-revappend lista ()) ) (defun my-revappend (lista1 lista2) (if (null lista1) lista2 (my-revappend (cdr lista1) (cons (car lista1) lista2)) ) )
list &rest args: constri e retorna uma lista com os argumentos dados. Aceita um nmero qualquer de argumentos. Com zero argumentos, retorna NIL.
(defun my-append2 (lista1 lista2) (if (null lista1) lista2 (cons (car lista1) (my-append2 (cdr lista1) lista2)) ) )
subst novo velho arvore: substitui uma expresso por outra numa lista, em todos os nveis (por isto chamamos de rvore).
41
(defun my-subst (novo velho arvore) (cond ((equal velho arvore) novo) ((atom arvore) arvore) (t (cons (my-subst novo velho (car arvore)) (my-subst novo velho (cdr arvore)) ) ) ) )
position item lista: retorna a primeira posio em que item aparece na lista. As posies so numeradas a partir de zero. retorna NIL. Se o item no est na lista,
(defun my-position (item lista) (cond ((null lista) nil) ((equal item (car lista)) 0) (t (let ((pos (my-position item (cdr lista)))) (and pos (1+ pos)) ) ) ) )
count item lista: retorna o nmero de ocorrncias do item na lista dada. subseq lista comeco &optional nal: retorna a subseqncia de uma lista, a partir de uma posio dada, e opcionalmente terminando numa outra posio dada. As posies so numeradas a partir de zero.
(defun my-subseq (lista comeco) (if (= comeco 0) lista (my-subseq (cdr lista) (1- comeco)) ) )
42
remove item lista: retorna uma nova lista obtida da lista dada pela remoo dos elementos iguais a item. A ordem relativa dos elementos restantes no alterada.
(defun my-remove (item lista) (cond ((null lista) nil) ((equal item (car lista)) (my-remove item (cdr lista))) (t (cons (car lista) (my-remove item (cdr lista)))) ) )
mapcar funcao lista: retorna uma lista composta do resultado de aplicar a funo dada a cada elemento da lista dada. Nota: funes com mais de um argumento podem ser usadas, desde que sejam fornecidas tantas listas quantos argumentos a funo requer. Se as listas no forem todas do mesmo tamanho, o resultado ter o comprimento da menor.
(defun my-mapcar1 (funcao lista) (if (null lista) nil (cons (funcall funcao (car lista)) (my-mapcar1 funcao (cdr lista)) ) ) )
Exerccios
1. Escreva a funo Pode usar a
de arugmentos.
43
my-
permitir testes sem comprometer a funo original denida no Common LISP. union lista1 lista2: retorna uma lista contendo todos os elementos que esto em uma das listas dadas. Se cada uma das listas dadas no contm elementos repetidos, garante-se que o resultado no contm repeties. Contudo, se as listas de entrada tiverem elementos repetidos, o resultado pode ou no conter repeties.
(defun my-union (lista1 lista2) (cond ((null lista1) lista2) ((member (car lista1) lista2) (my-union (cdr lista1) lista2)) (t (cons (car lista1) (my-union (cdr lista1) lista2)))
44
intersection lista1 lista2: retorna uma lista com os elementos comuns a lista1 e lista2. Se cada uma das listas dadas no contm elementos repetidos, garantese que o resultado no contm repeties. Contudo, se as listas de entrada tiverem elementos repetidos, o resultado pode ou no conter repeties.
(defun my-intersection (lista1 lista2) (cond ((null lista1) nil) ((member (car lista1) lista2) (cons (car lista1) (my-intersection (cdr lista1) lista2))) (t (my-intersection (cdr lista1) lista2)) ) )
set-dierence lista1 lista2: retorna uma lista com os elementos de lista1 que no esto em lista2.
(defun my-set-difference (lista1 lista2) (cond ((null lista1) nil) ((member (car lista1) lista2) (my-set-difference (cdr lista1) lista2)) (t (cons (car lista1) (my-set-difference (cdr lista1) lista2))) ) )
subsetp lista1 lista2: retorna verdadeiro quando cada elemento de lista1 aparece na lista2.
(defun my-subsetp (lista1 lista2) (cond ((null lista1) t) ((member (car lista1) lista2) (my-subsetp (cdr lista1) lista2)) (t nil) ) )
45
Todas estas funes admitem outras variaes atravs de parmetros adicionais ou maneiras diferentes de testar igualdade. Consulte a documentao ocial do Common Lisp para mais detalhes.
Exerccios
1. Escreva uma funo
prod-cart
duas listas dadas, onde os pares ordenados so representados por listas de dois elementos. Exemplo:
46
Cada pacote tm
seu nome. A lista de todos os pacotes existentes no sistema num certo momento pode ser obtida chamando-se a funo pr-denida
list-all-packages.
Quando um argumento para uma funo ou macro um pacote, ele geralmente dado como um smbolo cujo nome o nome do pacote. Um pacote tem smbolos internos e externos. Os smbolos externos de um pacote so a sua interface com o mundo exterior, por isso devem ter nomes bem escolhidos e anunciados a todos os usurios do sistema. pacotes. Smbolos internos so para uso interno apenas, e no devem ser acessados por outros
47
qualicao.
plo,
qualicados,
jogador:iniciar refere-se a um smbolo de nome iniciar num pacote chamamdo jogador. Para isto, o smbolo deve ser um smbolo externo do
referido pacote.
11.1.1
Importao e exportao
Por vezes, importante referir-se a smbolos de outros pacotes sem qualicao. Para este m, existe a exportao e a importao. Um smbolo de um pacote A, para ser vsivel pelo pacote B, deve ser exportado por A e importando por B. Vejamos como fazer isto. A funo
Ele pode
ento ser importado por outros pacotes. Para importar smbolos, existe a funo que recebe uma lista de
smbolos e os importa no pacote corrente. A partir da, eles podem ser usados sem qualicao. Outra possibilidade utilizar a funo
use-package,
que
internaliza no pacote corrente todos os smbolos externos do pacote usado como argumento. A partir da, eles podem ser usados sem qualicao.
keywords ),
(:), cujo valor como dado so eles mesmos e so constantes (no podem ter seu valor modicado).
48
make-package
recebe como argumento um smbolo, cujo nome ser o nome do novo pacote.
delete-package remove do sistema o pacote especicado. A macro in-package faz com que o seu argumento passe a ser o pacote corrente.
Para colocar num novo pacote um lote de denies, basta preceder as denies pelas linhas de cdigo abaixo:
Exerccios
1. Crie um novo pacote, dena nele uma funo e exporte esta funo. Depois v para o pacote a notao
49
A funo
make-array
12.1.2
Acessando arrays
A funo
aref
posio especicada pelos ndices. Por exemplo, se a varivel array criada no pargrafo anterior, a chamada elemento indexado por 2, 1 e 6 (equivalente a C ou
mat[2,1,6] setf
em Pascal).
A macro
aref
50
12.2 Loops
H vrias formas de fazer contrues iterativas em Lisp, mas aqui vamos apenas dar dois exemplos: as macros Lisp. A forma geral :
dolist e dotimes.
O leitor interessado
O formato
listform
seguida o corpo executado uma vez para cada elemento da lista, com a
var
dolist.
resultform
dotimes
mato geral :
Em
seguida o corpo executado uma vez para cada inteiro de zero ao valor deste inteiro menos um, com a varivel forma
resultform
dotimes.
Em ambos os casos, se
resultform
Exerccios
1. Escreva uma expresso que imprime os elementos de uma lista usando
dolist.
2. Escreva uma expresso que some os elementos de 0 a
n usando dotimes.
51
Bibliograa
[1] John L. McCarthy. Recursive functions of symbolic expressions and their computation by machine, part i. 195, 1960. [2] Edward H. Shortlie.
1990. ISBN 1-55558-041-6. [4] Joseph Weizenbaum. ELIZA - a computer program for the study of natu-
Communications
52