Documente Academic
Documente Profesional
Documente Cultură
Contedo
1
Programao
1.1 Linguagens de Programao . . . . . . . . . . . . . . . . . . .
1.2 Lisp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
10
11
12
13
14
14
Elementos da Linguagem
3.1 Elementos primitivos . . . . . . . . .
3.1.1 Nmeros . . . . . . . . . . . .
3.1.2 Cadeias de Caracteres . . . .
3.2 Combinaes . . . . . . . . . . . . .
3.3 Indentao . . . . . . . . . . . . . . .
3.4 Avaliao de Combinaes . . . . . .
3.5 Operadores de Strings . . . . . . . .
3.6 Definio de Funes . . . . . . . . .
3.7 Smbolos . . . . . . . . . . . . . . . .
3.8 Avaliao de Smbolos . . . . . . . .
3.9 Funes de Mltiplos Parmetros . .
3.10 Encadeamento de Funes . . . . . .
3.11 Funes Pr-Definidas . . . . . . . .
3.12 Aritmtica de Inteiros em Auto Lisp
3.13 Aritmtica de Reais em Auto Lisp .
3.14 Smbolos e Avaliao . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
16
16
17
18
20
22
23
24
27
28
29
30
30
33
36
38
.
.
.
.
.
.
.
.
.
.
40
40
41
43
44
47
51
54
56
57
59
Combinao de Dados
4.1 Coordenadas . . . . . . . . . . . . . .
4.2 Pares . . . . . . . . . . . . . . . . . .
4.3 Operaes com Coordenadas . . . .
4.4 Abstraco de Dados . . . . . . . . .
4.5 Coordenadas Tri-Dimensionais . . .
4.6 Coordenadas Bi- e Tri-Dimensionais
4.7 A Notao de Lista . . . . . . . . . .
4.8 tomos . . . . . . . . . . . . . . . . .
4.9 Tipos Abstractos . . . . . . . . . . . .
4.10 Coordenadas em AutoCad . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4.11
4.12
4.13
4.14
4.15
4.16
4.17
4.18
4.19
.
.
.
.
.
.
.
.
.
.
.
60
63
71
72
74
75
79
84
88
88
90
Modelao Tridimensional
5.1 Slidos Tridimensionais Pr-Definidos . . . . . . . . . . . . .
5.2 Modelao de Colunas Dricas . . . . . . . . . . . . . . . . .
92
92
97
Expresses Condicionais
6.1 Expresses Lgicas . . . . . . . . . . . . . . . . .
6.2 Valores Lgicos . . . . . . . . . . . . . . . . . . .
6.3 Predicados . . . . . . . . . . . . . . . . . . . . . .
6.4 Predicados Aritmticos . . . . . . . . . . . . . . .
6.5 Operadores Lgicos . . . . . . . . . . . . . . . . .
6.6 Predicados com nmero varivel de argumentos
6.7 Predicados sobre Cadeias de Caracteres . . . . .
6.8 Predicados sobre Smbolos . . . . . . . . . . . . .
6.9 Predicados sobre Listas . . . . . . . . . . . . . . .
6.10 Reconhecedores . . . . . . . . . . . . . . . . . . .
6.11 Reconhecedores Universais . . . . . . . . . . . .
6.12 Exerccios . . . . . . . . . . . . . . . . . . . . . . .
Coordenadas Polares . . . . . . . . . . . .
A funo command . . . . . . . . . . . . .
Variantes de Comandos . . . . . . . . . .
ngulos em Comandos . . . . . . . . . . .
Efeitos Secundrios . . . . . . . . . . . . .
A Ordem Drica . . . . . . . . . . . . . . .
Parameterizao de Figuras Geomtricas
Documentao . . . . . . . . . . . . . . . .
Depurao . . . . . . . . . . . . . . . . . .
4.19.1 Erros Sintticos . . . . . . . . . . .
4.19.2 Erros Semnticos . . . . . . . . . .
Estruturas de Controle
7.1 Sequenciao . . . . . . . . . . . .
7.2 Invocao de Funes . . . . . . . .
7.3 Variveis Locais . . . . . . . . . . .
7.4 Atribuio . . . . . . . . . . . . . .
7.5 Variveis Globais . . . . . . . . . .
7.6 Variveis Indefinidas . . . . . . . .
7.7 Propores de Vitrvio . . . . . . .
7.8 Seleco . . . . . . . . . . . . . . .
7.9 Seleco MltiplaA Forma cond
2
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
99
101
101
101
102
102
103
103
104
104
105
106
107
.
.
.
.
.
.
.
.
.
108
109
110
112
114
116
118
119
122
124
7.10
7.11
7.12
7.13
7.14
7.15
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
126
130
135
138
139
146
147
151
163
171
Programao
A transmisso de conhecimento um dos problemas que desde cedo preocupou a humanidade. Sendo o homem capaz de acumular conhecimento
ao longo de toda a sua vida, com desnimo que enfrenta a ideia de que,
com a morte, todo esse conhecimento se perca.
Para evitar esta perda, a humanidade inventou toda uma srie de mecanismos de transmisso de conhecimento. O primeiro, a transmisso oral,
consiste na transmisso do conhecimento de uma pessoa para um grupo reduzido de outras pessoas, de certa forma transferindo o problema da perda
de conhecimento para a gerao seguinte. O segundo, a transmisso escrita, consiste em registar em documentos o conhecimento que se pretende
transmitir. Esta forma tem a grande vantagem de, por um lado, poder chegar a muitas mais pessoas e, por outro, de reduzir significativamente o
risco de se perder o conhecimento por problemas de transmisso. De facto,
a palavra escrita permite preservar por muito tempo e sem qualquer tipo
de adulterao o conhecimento que o autor pretendeu transmitir.
graas palavra escrita que hoje conseguimos compreender e acumular um vastssimo conjunto de conhecimentos, muitos deles registados h
milhares de anos atrs.
Infelizmente, nem sempre a palavra escrita conseguiu transmitir com
rigor aquilo que o autor pretendia. A lngua natural tem inmeras ambiguidades e evolui substancialmente com o tempo, o que leva a que a interpretao dos textos seja sempre uma tarefa subjectiva. Quer quando escrevemos um texto, quer quando o lemos e o interpretamos, existem omisses,
imprecises, incorreces e ambiguidades que podem tornar a transmisso
de conhecimento falvel. Se o conhecimento que se est a transmitir for
simples, o receptor da informao, em geral, consegue ter a cultura e imaginao suficientes para conseguir ultrapassar os obstculos mas, no caso
da transmisso de conhecimentos mais complexos j isso poder ser muito
mais difcil.
Infelizmente, quando se exige rigor na transmisso de conhecimento,
fazer depender a compreenso desse conhecimento da capacidade de interpretao de quem o recebe pode ter consequncias desastrosas e, de facto,
a histria da humanidade est repleta de acontecimentos catastrficos cuja
causa , to somente, uma insuficiente ou errnea transmisso de conhecimento.
Para evitar estes problemas, inventaram-se linguagens mais rigorosas.
A matemtica, em particular, tem-se obssessivamente preocupado ao longo
dos ltimos milnios com a construo de uma linguagem onde o rigor seja
4
Neste caso, no s as reticncias deixam de fazer sentido como toda a frmula deixa de fazer sentido, o que mostra que, na verdade, a imaginao
necessria para a interpretao da frmula original no se restringia apenas
s reticncias mas sim a toda a frmula: o nmero de termos a considerar
depende do nmero do qual queremos saber o factorial.
Admitindo que o nosso leitor teria tido a imaginao suficiente para
descobrir esse detalhe, ele conseguiria tranquilamente calcular que 2! =
1 2 = 2. Ainda assim, casos haver que o deixaro significativamente
menos tranquilo. Por exemplo, qual o factorial de zero? A resposta no
parece bvia. E quanto ao factorial de 1? Novamente, no est claro. E
quanto ao factorial de 4.5? Mais uma vez, a frmula nada diz e a nossa
imaginao tambm no consegue adivinhar.
Ser possvel encontrar uma forma de transmitir o conhecimento da
funo factorial que minimize as imprecises, lacunas e ambiguidades?
Ser possvel reduzir ao mnimo razovel a imaginao necessria para
compreender esse conhecimento? Experimentemos a seguinte variante da
definio da funo factorial:
(
1,
se n = 0
n! =
n (n 1)!, se n N.
Teremos agora atingido o rigor suficiente que dispensa imaginao por
parte do leitor? A resposta estar na anlise dos casos que causaram problemas definio anterior. Em primeiro lugar, no existem reticncias, o
que positivo. Em segundo lugar, para o factorial de 2 temos, pela definio:
2! = 2 1! = 2 (1 0!) = 2 (1 1) = 2 1 = 2
ou seja, no h qualquer ambiguidade. Finalmente, vemos que no faz
sentido determinar o factorial de 1 ou de 4.5 pois a definio apresentada
apenas se aplica aos membros de N0 .
Este exemplo mostra que, mesmo na matemtica, h diferentes graus
de rigor nas diferentes formas como se expe o conhecimento. Algumas
dessas formas exigem um pouco mais de imaginao e outras um pouco
menos mas, em geral, qualquer delas tem sido suficiente para que a humanidade tenha conseguido preservar o conhecimento adquirido ao longo da
sua histria.
Acontece que, actualmente, a humanidade conta com um parceiro que
tem dado uma contribuio gigantesca para o seu progresso: o computador. Esta mquina tem a extraordinria capacidade de poder ser instruda
de forma a saber executar um conjunto complexo de tarefas. A actividade
6
1.1
Linguagens de Programao
1.2
Lisp
1.3
Exerccios
2.1
Quando comparada com a grande maioria das outras linguagens de programao, a linguagem Lisp possui uma sintaxe extraordinariamente simples baseada no conceito de expresso.1
Uma expresso, em Lisp, pode ser construda empregando elementos
primitivos como, por exemplo, os nmeros; ou combinando outras expresses entre si como, por exemplo, quando somamos dois nmeros. Como
iremos ver, esta simples definio permite-nos construir expresses de complexidade arbitrria. No entanto, convm relembrarmos que a sintaxe restringe aquilo que podemos escrever: o facto de podermos combinar expresses para produzir outras expresses mais complexas no nos autoriza
a escrever qualquer combinao de subexpresses. As combinaes obedecem a regras sintticas que iremos descrever ao longo do texto.
semelhana do que acontece com a sintaxe, tambm a semntica da
linguagem Lisp , em geral, substancialmente mais simples que a de outras
linguagens de programao. Como iremos ver, a semntica determinada
pelos operadores que as nossas expresses iro empregar. Um operador de
soma, por exemplo, serve para somar dois nmeros. Uma combinao que
junte este operador e, por exemplo, os nmeros 3 e 4 tem, como significado, a soma de 3 com 4, i.e., 7. No caso das linguagens de programao, a
semntica de uma expresso dada pelo computador que a vai avaliar.
2.2
O Avaliador
11
_$
Elementos da Linguagem
na matemtica h j muito tempo. A potenciao , portanto, uma abstraco de uma sucesso de multiplicaes.
Tal como a linguagem da matemtica, uma linguagem de programao
deve possuir dados e procedimentos primitivos, deve ser capaz de combinar quer os dados quer os procedimentos para produzir dados e procedimentos mais complexos e deve ser capaz de abstrair padres de clculo de
modo a permitir trat-los como operaes simples, definindo novas operaes que representem esses padres de clculo.
Mais frente iremos ver como possvel definir essas abstraces em
Lisp mas, por agora, vamos debruar-nos sobre os elementos mais bsicos,
os chamados elementos primitivos da linguagem.
3.1
Elementos primitivos
Nmeros
13
Cadeias de Caracteres
As cadeias de caracteres (tambm denominadas strings) so outro tipo de dados primitivo. Um carcter uma letra, um dgito ou qualquer outro smbolo grfico, incluindo os smbolos grficos no visveis como o espao, a
tabulao e outros. Uma cadeia de caracteres especificada atravs de uma
sequncia de caracteres delimitada por aspas. Tal como com os nmeros, o
valor de uma cadeia de caracteres a prpria cadeia de caracteres.
_$ "Ola"
"Ola"
_$ "Eu sou o meu valor"
"Eu sou o meu valor"
Sendo uma string delimitada por aspas fica a dvida sobre como criar
uma string que contm aspas. Para isso, e para outros caracteres especiais,
existe um carcter que o Auto Lisp interpreta de forma distinta: quando,
na criao de uma string, aparece o carcter \ ele assinala que o prximo
carcter tem de ser processado de forma especial. Por exemplo, para se a
criar a string correspondente frase
O Manuel disse Bom dia! ao Pedro.
temos de escrever:
"O Manuel disse \"Bom dia!\" ao Pedro."
14
Sequncia
\\
\"
\e
\n
\r
\t
\nnn
Resultado
o carcter \ (backslash)
o carcter " (aspas)
o carcter escape
o carcter de mudana de linha (newline)
o carcter de mudana de linha (carriage return)
o carcter de tabulao (tab)
o carcter cujo cdigo octal nnn
3.2
Combinaes
Uma combinao uma expresso que descreve a aplicao de um operador aos seus operandos. Por exemplo, na matemtica, os nmeros podem
ser combinados usando operaes como a soma ou o produto. Como exemplo de combinaes matemticas, temos 1+2 e 1+23. A soma e o produto
de nmeros so exemplos de operaes extremamente elementares consideradas procedimentos primitivos.
Em Lisp, cria-se uma combinao escrevendo uma sequncia de expresses entre um par de parnteses. Uma expresso um elemento primitivo
ou uma outra combinao. A expresso (+ 1 2) uma combinao dos
elementos primitivos 1 e 2 atravs do procedimento primitivo +. J no
caso (+ 1 (* 2 3)) a combinao entre 1 e (* 2 3), sendo esta ltima
expresso uma outra combinao. Note-se que cada expresso deve ser
separada das restantes por um ou mais espaos. Assim, embora a combinao (* 2 3) possua as trs expresses *, 2 e 3, a combinao (*2 3) s
possui duas*2 e 3sendo que a primeira delas no tem qualquer significado pr-definido.
Por agora, as nicas combinaes com utilidade so aquelas em que as
expresses correspondem a operadores e operandos. Por conveno, o Lisp
considera que o primeiro elemento de uma combinao um operador e os
restantes so os operandos.
A notao que o Lisp utiliza para construir expresses (operador primeiro e operandos a seguir) designada por notao prefixa por o operador ocorrer prviamente aos operandos. Esta notao costuma causar alguma perplexidade a quem inicia o estudo da linguagem, que espera uma
notao mais prxima da que aprendeu em aritmtica e que usada habitualmente nas outras linguagens de programao. Nestas, a expresso
(+ 1 (* 2 3)) usualmente escrita na forma 1 + 2 * 3 (designada no15
16
3.3
Indentao
A desvantagem da notao prefixa est na escrita de combinaes complexas. Por exemplo, a expresso 1+2*3-4/5*6 l-se com relativa facilidade
mas, quando escrita na sintaxe do Lisp,(- (+ 1 (* 2 3)) (* (/ 4 5) 6)),
fica com uma forma que, para quem no est ainda habituado, pode ser
mais difcil de perceber devido acumulao de parnteses.
Para tornarmos estas expresses mais fceis de entender, podemos (e
devemos) empregar a tcnica da indentao. Esta tcnica baseia-se no uso
de diferentes alinhamentos na disposio textual dos programas de modo a
facilitar a sua leitura. Assim, ao invs de escrevermos as nossas expresses
todas numa linha ou com arranjos arbitrrios entre linhas, escrevemo-las
ao longo de vrias linhas e com um alinhamento entre linhas que mostre o
relacionamento das vrias subexpresses com a expresso que as contm.
A regra para indentao de combinaes Lisp extremamente simples:
numa linha coloca-se o operador e o primeiro operando; os restantes operandos vm alinhados por debaixo do primeiro, usando-se um nmero suficiente de espaos em branco esquerda para que os operandos fiquem
correctamente arrumados. No caso de uma expresso ser curta, podemos
escrev-la numa s linha, com os operandos logo a seguir ao operador, com
um espao em branco entre cada um. Usando estas duas regras, podemos
reescrever a expresso anterior na seguinte forma, onde usamos linhas verticais imaginrias para salientar a indentao:
(- (+ 1
(* 2 3))
(* (/ 4 5)
6))
Quando a regra de indentao no suficiente para produzir uma disposio de linhas de texto que seja esteticamente agradvel, usam-se pequenas variaes, como seja colocar o operador numa linha e os operandos
por debaixo, por exemplo:
(um-operador-com-um-nome-muito-grande
1 2 3 4)
18
7. 1 (2 + 3)
8. 2 2 + 3 3 3
Exerccio 3.3.4 Converta as seguintes expresses da notao prefixa do Lisp para a notao
infixa da aritmtica:
1.
2.
3.
4.
5.
6.
7.
(*
(*
(/
(/
(/
((-
(/ 1 2) 3)
1 (- 2 3))
(+ 1 2) 3)
(/ 1 2) 3)
1 (/ 2 3))
(- 1 2) 3)
1 2 3)
Exerccio 3.3.5 Indente a seguinte expresso de modo a ter um nico operando por linha.
(* (+ (/ 3 2) (- (* (/ 5 2) 3) 1) (- 3 2)) 2)
3.4
Avaliao de Combinaes
Como j vimos, o Lisp considera que o primeiro elemento de uma combinao um operador e os restantes so os operandos.
O avaliador determina o valor de uma combinao como o resultado de
aplicar o procedimento especificado pelo operador ao valor dos operandos.
O valor de cada operando designado de argumento do procedimento.
Assim, o valor da combinao (+ 1 (* 2 3)) o resultado de somar o
valor de 1 com o valor de (* 2 3). Como j se viu, 1 vale 1 e (* 2 3)
uma combinao cujo valor o resultado de multiplicar o valor de 2 pelo
valor de 3, o que d 6. Finalmente, somando 1 a 6 obtemos 7.
_$ (* 2 3)
6
_$ (+ 1 (* 2 3))
7
3.5
Operadores de Strings
Para alm dos operadores que j vimos para nmeros, existem operadores
para strings. Por exemplo, para concatenar vrias strings, existe o operador
strcat. A concatenao de vrias strings produz uma s string com todos
os caracteres dessas vrias strings e pela mesma ordem:
_$ (strcat "1" "2")
"12"
_$ (strcat "um" "dois" "tres" "quatro")
"umdoistresquatro"
_$ (strcat "eu" " " "sou" " " "uma" " " "string")
"eu sou uma string"
_$ (strcat "E eu" " sou " "outra")
"E eu sou outra"
_$ (substr "abcd" 1)
"abcd"
_$ (substr "abcd" 2)
"bcd"
_$ (substr "abcd" 2 2)
"bc"
Exerccio 3.5.1 Qual o resultado das seguintes avaliaes?
1. (strcat "a" "vista" "da" " baixa" "da" " banheira")
2. (substr (strcat "Bom dia") 1 3)
3. (substr (strcat "Bom dia") 5)
3.6
Definio de Funes
Para alm das operaes bsicas aritmticas, a matemtica disponibilizanos um vastssimo conjunto de outras operaes que se definem custa
daquelas. Por exemplo, o quadrado de um nmero uma operao (tambm
designada por funo) que, dado um nmero, produz o resultado de multiplicar esse nmero por ele prprio. Matematicamente falando, define-se o
quadrado de um nmero pela funo x2 = x x.
Tal como em matemtica, pode-se definir numa linguagem de programao a funo que obtm o quadrado de um nmero. Em Lisp, para
obtermos o quadrado de um nmero qualquer, por exemplo, 5, escrevemos a combinao (* 5 5). No caso geral, dado um nmero qualquer x,
sabemos que obtemos o seu quadrado escrevendo (* x x). Falta apenas
associar um nome que indique que, dado um nmero x, obtemos o seu quadrado avaliando (* x x). Lisp permite-nos fazer isso atravs da operao
defun (abreviatura de define function):
_$ (defun quadrado (x) (* x x))
QUADRADO
Como se pode ver pela definio da funo quadrado, para se definirem novos procedimentos em Lisp, necessrio criar uma combinao
de quatro elementos. O primeiro elemento desta combinao a palavra
defun, que informa o avaliador que estamos a definir uma funo. O segundo elemento o nome da funo que queremos definir, o terceiro elemento uma combinao com os parmetros da funo e o quarto elemento
a expresso que determina o valor da funo para aqueles parmetros. De
modo genrico podemos indicar que a definio de funes feita usando
a seguinte forma:
(defun nome (parmetro1 ... parmetron )
corpo)
22
todas as ocorrncias de x pelo valor 3, i.e., o valor final ser o da combinao (* 3 3).
Para se perceber a avaliao de combinaes que o Lisp emprega, til
decompor essa avaliao nas suas etapas mais elementares. No seguinte
exemplo mostramos o processo de avaliao para a expresso
(quadrado (quadrado (+ 1 2)))
(quadrado (* 3 3))
(quadrado 9)
(* 9 9)
81
Como dissemos, a definio de funes permite-nos associar um procedimento a um nome. Isto implica que o Lisp tem de possuir uma memria
onde possa guardar a funo e a sua associao ao nome dado. Esta memria do Lisp designa-se ambiente.
Note-se que este ambiente apenas existe enquanto estamos a trabalhar
com a linguagem. Quando terminamos, perde-se todo o ambiente. Para
evitar perdermos as definies de procedimentos que tenhamos feito, convm regist-las num suporte persistente, como seja um ficheiro. Para facilitar a utilizao, o Lisp permite que se avaliem as diversas definies a partir de um ficheiro. Por este motivo, o processo usual de trabalho com Lisp
consiste em escrever as vrias definies em ficheiros embora se continue
a usar o avaliador de Lisp para experimentar e testar o correcto funcionamento das nossas definies.
Exerccio 3.6.1 Defina a funo dobro que, dado um nmero, calcula o seu dobro.
23
3.7
Smbolos
24
3.8
Avaliao de Smbolos
25
3.9
J vimos e definimos vrias funes em Lisp. At agora, todas as que definimos tinham um nico parmetro mas, obviamente, possvel definir
funes com mais do que um parmetro.
Por exemplo, a rea A de um tringulo de base b e altura c define-se
matematicamente por A(b, c) = bc
2 . Em Lisp, teremos:
(defun A (b c) (/ (* b c) 2))
Quando o nmero de definies aumenta torna-se particularmente importante para quem as l que se perceba rapidamente o seu significado e,
por isso, de crucial importncia que se faa uma boa escolha de nomes.
Exerccio 3.9.1 Defina uma funo que calcula o volume de um paralelippedo a partir do
seu comprimento, altura e largura. Empregue nomes suficientemente claros.
Exerccio 3.9.2 Defina a funo media que calcula o valor mdio entre dois outros valores.
Por exemplo (media 2 3)2.5.
3.10
Encadeamento de Funes
3.11
Funes Pr-Definidas
A possibilidade de se definirem novas funes fundamental para aumentarmos a flexibilidade da linguagem e a sua capacidade de se adaptar aos
problemas que pretendemos resolver. As novas funes, contudo, precisam
27
x escreve-se como (sqrt x). O nome sqrt uma contraco do Ingls square root e contraces semelhantes so empregues para vrias outras
funes. Por exemplo, a funo valor absoluto |x| escreve-se (abs x) (de
absolute value), a funo parte inteira bxc escreve-se (fix x) (de fixed point)
e a funo potncia xy que se escreve (expt x y) (de exponential). A Tabela 3 mostra as equivalncias mais relevantes entre invocaes de funes
em Auto Lisp e as correspondentes invocaes na Matemtica.
A Tabela 4 apresenta uma seleco de funes sobre strings pr-definidas
do Auto Lisp. medida que formos apresentando novos tpicos do Auto
Lisp iremos explicando outras funes pr-definidas que sejam relevantes
para o assunto.
Exerccio 3.11.1 Como pode verificar pelas Tabelas 2 e 3, em Auto Lisp, uma multiplicao
sem argumentos produz o valor zero, tal como acontece no caso de uma diviso sem argumentos. No entanto, os matemticos contestam este resultado, afirmando que est errado
e que o valor correcto deveria ser outro. Concorda? Em caso afirmativo, qual deveria ser o
valor correcto?
Exerccio 3.11.2 Embora o seno (sin) e o cosseno (cos) sejam funes pr-definidas em
sin x
Auto Lisp, a tangente (tan) no . Defina-a a partir da frmula tan x = cos
.
x
Exerccio 3.11.3 Do conjunto das funes trigonomtricas inversas, o Auto Lisp apenas providencia o arco tangente (atan). Defina tambm as funes arco-seno (asin) e arco-cosseno
28
1 x2
acos x = atan
x
Exerccio 3.11.4 A funo fix permite truncar um nmero real, produzindo o nmero inteiro que se obtm pela eliminao da parte fraccionria desse real. Defina a funo round
que permite arredondar um nmero real, i.e., produzir o inteiro que mais prximo desse
nmero real.
Exerccio 3.11.5 Para alm da funo round que arredonda para o inteiro mais prximo
e da funo fix que arredonda para baixo, usual considerar ainda a funo ceiling
que arrendonda para cima. Defina esta funo.
Exerccio 3.11.6 Traduza as seguintes expresses matemticas para Auto Lisp:
q
1
1.
log 2|(39 log 25)|
2.
3.
cos4 2
atan 3
1
2
3 + sin 2 2
Exerccio 3.11.7 Traduza as seguintes expresses Auto Lisp para a notao matemtica:
1. (log (sin (+ (expt 2 4) (/ (fix (atan pi)) (sqrt 5)))))
2. (expt (cos (cos (cos 0.5))) 5)
3. (sin (/ (cos (/ (sin (/ pi 3)) 3)) 3))
Exerccio 3.11.8 Defina o predicado impar? que, dado um nmero, testa se ele mpar,
i.e., se o resto da diviso desse nmero por dois um. Para calcular o resto da diviso de
um nmero por outro, utilize a funo pr-definida rem.
Exerccio 3.11.9 Em vrias actividades usual empregarem-se expresses padronizadas.
Por exemplo, se o aluno Passos Dias Aguiar pretende obter uma certido de matrcula da
universidade que frequenta, ter de escrever uma frase da forma:
Passos Dias Aguiar vem respeitosamente pedir a V. Exa. que se digne
passar uma certido de matrcula.
Por outro lado, se a aluna Maria Gustava dos Anjos pretende um certificado de habilitaes, dever escrever:
Maria Gustava dos Anjos vem respeitosamente pedir a V. Exa. que se
digne passar um certificado de habilitaes.
29
Para simplificar a vida destas pessoas, pretende-se que implemente uma funo denominada requerimento que, convenientemente parameterizada, gera uma string com a
frase apropriada para qualquer um dos fins anteriormente exemplificados e tambm para
outros do mesmo gnero que possam vir a ser necessrios. Teste a sua funo para garantir
que consegue reproduzir os dois exemplos anteriores passando o mnimo de informao
nos argumentos da funo.
Exerccio 3.11.10 Tambm na actividade da Arquitectura, usual os projectos necessitarem de informaes textuais escritas numa forma padronizada. Por exemplo, considere as
seguintes trs frases contidas nos Cadernos de Encargos de trs diferentes projectos:
Toda a caixilharia ser metlica, de alumnio anodizado, cor natural, construda com os perfis utilizados pela Serralharia do Corvo (ou semelhante),
sujeitos a aprovao da Fiscalizao.
Toda a caixilharia ser metlica, de alumnio lacado, cor branca, construda com os perfis utilizados pela Technal (ou semelhante), sujeitos a aprovao da Fiscalizao.
Toda a caixilharia ser metlica, de ao zincado, preparado com primrios de aderncia, primrio epoxdico de proteco e acabamento com esmalte
SMP, cor 1050-B90G (NCS), construda com os perfis standard existentes no
mercado, sujeitos a aprovao da Fiscalizao.
Defina uma funo que, convenientemente parameterizada, gera a string adequada
para os trs projectos anteriores, tendo o cuidado de a generalizar para qualquer outra
situao do mesmo gnero.
3.12
Vimos que o Auto Lisp disponibiliza, para alm dos operadores aritmticos
usuais, um conjunto de funes matemticas. No entanto, h que ter em
conta que existem diferenas substanciais entre o significado matemtico
destas operaes e a sua implementao no Auto Lisp.
Um primeiro problema importante tem a ver com a gama de inteiros.
Em Auto Lisp, os inteiros so representados com apenas 32 bits de informao.6 Isto implica que apenas se conseguem representar inteiros desde
2147483647 at 2147483647. Para tornar a situao ainda mais problemtica, embora exista esta limitao, quando ela no respeitada o Auto Lisp
no emite qualquer aviso. Este comportamento usual na maioria das linguagens de programao e est relacionado com questes de performance.7
6
Em AutoCad, a gama de inteiros ainda mais pequena pois a sua representao apenas
usa 16 bits, permitindo apenas representar os inteiros de 32768 a 32767. Isto no afecta o
Auto Lisp excepto quando este tem de passar inteiros para o AutoCad.
7
Curiosamente, a maioria dos dialectos de Lisp (mas no o Auto Lisp) no apresenta este
comportamento, preferindo representar nmeros inteiros com dimenso to grande quanto
for necessrio.
30
2147483648
+
2 1 0 +1 +2
1 0 +1
2147483648
+2147483647
+2
+2147483647
Note-se que estamos apenas a falar da leitura de nmeros. Como j vimos, as operaes
aritmticas usuais no apresentam este comportamento.
9
Este exemplo mostra que, em Auto Lisp, h um inteiro que no pode ser lido mas que
pode ser produzido como resultado de operaes aritmticas. importante salientar que
este comportamento verdadeiramente bizarro exclusivo do Auto Lisp e no se verifica em
mais nenhum dialecto de Lisp.
32
_$ (- -2147483647 1)
-2147483648
_$ (- -2147483648 1)
-2.14748e+009
_$ (- -2147483647 2)
2147483647
Exerccio 3.12.3 A rea A de um pentgono regular inscrito num crculo de raio r dada
pela frmula
q
5
A = r2 10 + 2 5
8
Defina uma funo Auto Lisp que calcule essa rea.
Exerccio 3.12.4 Defina uma funo que calcula o volume de um elipside de semi-eixos a,
b e c. Esse volume pode ser obtido pela frmula V = 34 abc.
3.13
Em relao aos reais, o seu comportamento mais prximo do que se considera matematicamente correcto mas, ainda assim, h vrios problemas
com que preciso lidar.
A gama dos reais vai desde 4.94066 10324 at 1.79769 10+308 . Se o
Auto Lisp tentar ler um nmero real que excede esta gama ele imediatamente convertido para um nmero especial que representa o infinito:
_$ 2e400
1.#INF
_$ -2e400
-1.#INF
As operaes com nmeros reais tm a vantagem de a maioria dos computadores actuais conseguirem detectar o overflow de reais e reagirem em
conformidade (gerando um erro ou simplesmente produzindo uma representao do infinito). Como vimos anteriormente, se se tivessem usado
nmeros inteiros, ento o overflow no seria sequer detectado, produzindo
comportamentos aparentemente bizarros, como, por exemplo, o produto
de dois nmeros positivos ser um nmero negativo.
H ainda dois outros problemas importantes relacionados com reais:
erros de arredondamento e reduo de preciso na escrita. A ttulo de
exemplo, consideremos a bvia igualdade matemtica ( 43 1) 3 1 = 0 e
comparemos os resultados que se obtm usando inteiros ou reais:
_$ (- (* (- (/ 4 3) 1) 3) 1)
-1
_$ (- (* (- (/ 4.0 3.0) 1.0) 3.0) 1.0)
-2.22045e-016
Como se pode ver, nem usando inteiros, nem usando reais, se consegue
obter o resultado correcto. No caso dos inteiros, o problema causado pela
diviso inteira de 4 por 3 que produz 1. No caso dos reais, o problema
causado por erros de arrendondamento: 4/3 no representvel com um
nmero finito de dgitos. Este erro de arrendondamento ento propagado
nas restantes operaes produzindo um valor que, embora no seja zero,
est muito prximo.
Obviamente, como o resultado da avaliao com reais suficientemente
pequeno, podemos convert-lo para o tipo inteiro (aplicando-lhe uma truncatura com a funo fix) e obtemos o resultado correcto:
_$ (fix (- (* (- (/ 4.0 3.0) 1.0) 3.0) 1.0))
0
3.14
Smbolos e Avaliao
1)
"Bom dia!")
pi)
quadrado)
+)
35
Como podemos ver, a funo type devolve-nos o tipo do seu argumento: INT para inteiros, STR para strings, REAL para reais, etc.
Mas o que so estes resultadosINT, STR, REAL, etc que foram devolvidos pela funo type? Que tipo de objectos so? Para responder
questo, o melhor usar a mesmssima funo type:
_$ (type pi)
REAL
_$ (type (type pi))
SYM
SYM a abreviatura de symbol, indicando que o objecto que devolvido pela funo type um smbolo. Note-se que, contrariamente ao que
acontece com o smbolo pi que est associado ao nmero 3.141519 . . . , os
smbolos REAL, INT, STR, etc., no esto associados a nada, eles apenas so
usados como representao do nome de um determinado tipo de dados.
Se os valores devolvidos pela funo type so objectos do tipo smbolo,
ento dever ser possvel design-los, tal como designamos os nmeros ou
as strings. Mas qual ser o modo de o fazermos? Uma hiptese (errada) seria escrev-lo tal como escrevemos nmeros ou strings. Acontece que isto
possvel no caso dos nmeros e strings pois eles avaliam para eles prprios.
J no caso dos smbolos, sabemos que no avaliam para eles prprios, antes avaliando para as entidades a que esto associados naquele momento.
Assim, se quisermos designar o smbolo pi, no bastar escrev-lo numa
expresso pois o que ir resultar aps a sua avaliao no ser um smbolo
mas sim o nmero 3.141519 . . . que o valor desse smbolo.
Para ultrapassar este problema precisamos de, por momentos, alterar a
semntica habitual que o Lisp atribui aos smbolos. Essa semntica, recordemonos, a de que o valor de um smbolo a entidade a que esse smbolo est
associado nesse momento e esse valor surge sempre que o Lisp avalia o
smbolo. Para alterarmos essa semntica, precisamos de indicar ao Lisp
que no queremos que ele avalie um determinado smbolo, i.e., queremos
que ele trate o smbolo como ele , sem o avaliar. Para isso, o Lisp disponibiliza a forma quote. Esta forma, que recebe um nico argumento,
tem uma semntica simplicssima: devolve o argumento sem este ter sido
avaliado. Reparemos na seguinte interaco:
_$ pi
3.14159
_$ (quote pi)
PI
_$ (+ 1 2 3)
36
6
_$ (quote (+ 1 2 3))
(+ 1 2 3)
Combinao de Dados
4.1
Coordenadas
A Arquitectura pressupe a localizao de elementos no espao. Essa localizao expressa-se em termos do que se designa por coordenadas: as coordenadas de um ponto identificam univocamente esse ponto no espao.
Se o espao for bi-dimensional (abreviadamente, 2D), cada ponto identificado por duas coordenadas. Se o espao for tri-dimensional (3D), cada
37
x
Figura 2: Coordenadas rectangulares e polares.
ponto identificado por trs coordenadas. Por agora, vamos considerar
apenas o caso de coordenadas bi-dimensionais.
Existem vrios sistemas de coordenadas bi-dimensionais possveis mas
os mais usais so o sistema de coordenadas rectangulares e o sistemas de
coordenadas polares, representados na Figura 2. No sistema de coordenadas rectangulares, esse par de nmeros designa a abcissa x e a ordenada y.
No sistema de coordenadas polares, esse par de nmeros designa o raio vector e o ngulo polar . Em qualquer caso, as coordenadas bi-dimensionais
so descritas por um par de nmeros.
Como vimos nas seces anteriores, o Auto Lisp sabe lidar com o conceito de nmeros. Vamos agora ver que ele tambm sabe lidar com o conceito de par.
4.2
Pares
O cons para o Lisp o mesmo que as tabelas (arrays) e estruturas (records, structs)
so para as outras linguagens como Pascal ou C. Na prtica, o cons um mecanismo de
agregao de entidades.
38
A representao grfica anterior denomina-se notao de caixa e ponteiro precisamente porque mostra os pares como caixas com ponteiros
para os elementos dos pares.
Uma vez que a construo de um par feita usando uma funo, a sua
invocao segue as mesmas regras de avaliao de todas as outras invocaes de funes, ou seja, as expresses que constituem os argumentos
so avaliadas e so os resultados dessas avaliaes que so usados como
elementos do par. Assim, temos:
_$ (cons (+ 1 2) (* 3 4))
(3 . 12)
_$ (cons 1 "dois")
(1 . "dois")
_$ (cons (area-circulo 10) (area-triangulo 20 30))
(314.159 . 300)
39
4.3
A partir do momento em que sabemos construir pares, podemos criar coordenadas e podemos definir operaes sobre essas coordenadas. Para criarmos coordenadas podemos simplesmente juntar num par os dois nmeros
que representam a abcissa e a ordenada. Por exemplo, o ponto do espao
cartesiano (1, 2) pode ser construdo atravs de:
_$ (cons 1 2)
(1 . 2)
Uma vez que estamos a fazer um par que contm, primeiro, a abcissa e,
depois, a ordenada, podemos obter estes valores usando, respectivamente,
as funes car e cdr.
Para melhor percebermos a utilizao destas funes, imaginemos que
pretendemos definir uma operao que mede a distncia d entre os pontos
P0 = (x0 , y0 ) e P1 = (x1 , y1 ) que podemos ver na Figura 3. A distncia d
corresponde, logicamente, ao comprimento da recta que une P0 a P1 .
40
P1
y1
d
y0
P0
x0
x1
4.4
Abstraco de Dados
41
A construo de coordenadas bi-dimensionais por intermdio da funo xy apenas o primeiro passo para abstrairmos a utilizao dos pares.
O segundo passo a criao de funes que acedem abcissa x e ordenada y das coordenadas (x, y). Para isso, vamos definir, respectivamente,
11
42
As funes xy, cx e cy constituem uma abstraco das coordenadas bidimensionais que nos permitem escrever as funes que manipulam coordenadas sem termos de pensar na sua implementao em termos de pares.
Esse facto torna-se evidente quando reescrevemos a funo distancia-2d
em termos destas novas funes:
(defun distancia-2d (p0 p1)
(sqrt (+ (quadrado (- (cx p1) (cx p0)))
(quadrado (- (cy p1) (cy p0))))))
Tal como a funo xy poderia ter um nome mais explcito, tambm as funes
que acedem abcissa e ordenada se poderiam denominar abcissa e ordenada ou
coordenada-x e coordenada-y ou qualquer outro par de nomes suficientemente claro.
No entanto, sendo as coordenadas um tipo de dados com muito uso, mais uma vez se tornar vantajoso que empreguemos nomes curtos.
43
P0
y
P
Uma vez que esta funo recebe coordenadas como argumento e produz coordenadas como resultado, ela constitui outra importante adio ao
conjunto de operaes disponveis para lidar com coordenadas. Naturalmente, podemos usar a funo +xy para definir novas funes como, por
exemplo, os casos particulares de deslocamento horizontal e vertical que se
seguem:
(defun +x (p dx)
(+xy p dx 0))
(defun +y (p dy)
(+xy p 0 dy))
4.5
Coordenadas Tri-Dimensionais
As coordenadas bi-dimensionais localizam pontos num plano. A localizao de pontos no espao requer coordenadas tri-dimensionais. Tal como
acontecia com as coordenadas bi-dimensionais, tambm existem vrios sistemas de coordenadas tri-dimensionais, nomeadamente, o sistema de coordenadas rectangulares, o sistema de coordenadas cilndricas e o sistema
44
x
P
x
Figura 5: Coordenadas Cartesianas
de coordenadas esfricas. Em qualquer deles, a localizao de um ponto no
espao feita custa de trs parmetros independentes. As coordenadas
tri-dimensionais so, por isso, triplos de nmeros.
Nesta seco vamos debruar-nos apenas sobre o sistema de coordenadas rectangulares, tambm conhecidas por coordenadas Cartesianas em
honra ao seu inventor: Ren Descartes. Estas coordenadas esto representadas na Figura 5.
Como vimos na seco anterior, o Auto Lisp disponibiliza a operao
cons para permitir formar pares de elementos, o que nos permitiu traduzir as coordenadas bi-dimensionais da geometria para pares de nmeros
em Auto Lisp. Agora, a situao ligeiramente mais complexa pois o Auto
Lisp no disponibiliza nenhuma operao capaz de fazer triplos de nmeros. Ou qudruplos. Ou quntuplos. Ou, na verdade, qualquer outro tipo
de tuplo para alm dos duplos.
Na realidade, esta aparente limitao do Auto Lisp perfeitamente justificada pois trivial, a partir de pares, formarmos qualquer tipo de agrupamento que pretendamos. Um triplo pode ser feito custa de dois pares: um
contendo dois elementos e outro contendo este par e o terceiro elemento.
Um qudruplo pode ser feito custa de trs pares: um par para cada dois
elementos e um terceiro par contendo os dois pares anteriores. Um quntuplo pode ser feito custa de quatro pares: trs pares para formar um
qudruplo e um quarto par para juntar o qudruplo ao quinto elemento.
Agrupamentos com maior nmero de elementos podem ser formados simplesmente seguindo esta estratgia.
45
z
y
Notemos que as funes que seleccionam os componentes das coordenadas tm de ser consistentes com os pares construdos pela funo xyz.
Uma vez que a coordenada x o elemento da esquerda do par que o elemento da esquerda do par que contm os componentes das coordenadas,
precisamos de empregar duas vezes a funo car na definio da funo
cx. Do mesmo modo, a coordenada y o elemento da direita do par que
46
p1)
(cx p1) (cx p0)))
(cy p1) (cy p0)))
(cz p1) (cz p0))))))
Tal como acontecia com a funo +xy, tambm a funo +xyz independente do arranjo particular de pares que usemos para implementar as
coordenadas tri-dimensionais. Desde que mantenhamos a consistncia entre as funes cx, cy e cz, que seleccionam os componentes das coordenadas tri-dimensionais, e a funo xyz que cria coordenadas tri-dimensionais
a partir dos seus componentes, podemos livremente empregar outros arranjos de pares.
Exerccio 4.5.1 Defina a funo +z que, dado um ponto em coordenadas tri-dimensionais,
calcula as coordenadas do ponto que lhe est directamente por cima distncia z .
Exerccio 4.5.2 Defina a funo ponto-medio que calcula as coordenadas tridimensionais
do ponto mdio entre dois outros pontos P0 e P1 descritos tambm pelas suas coordenadas
tridimensionais.
4.6
seria desejvel podermos ter uma nica operao cx capaz de obter a coordenada x quer de coordenadas bi-dimensionais, quer de coordenadas tridimensionais. Logicamente, o mesmo podemos dizer da operao cy.
Para isso, necessrio repensarmos a forma como implementamos as
coordenadas em termos de pares, de modo a encontrarmos um arranjo de
pares que seja utilizvel por ambos os tipos de coordenadas. Para simplificar, podemos comear por considerar que, semelhana do que fizemos
para o caso bi-dimensional, usamos um primeiro par para conter a coordenada x, tal como se apresenta em seguida:
Falta agora incluirmos a coordenada y no caso bi-dimensional e as coordenadas y e z no caso tri-dimensional. Se o objectivo termos um arranjo
de pares que funcione para os dois casos, ento crucial que a coordenada
y fique armazenada de forma idntica em ambos. Uma vez que as coordenadas tri-dimensionais exigem pelo menos mais um par, podemos arbitrar
a seguinte soluo:
x
y
49
x
y
nil
x
y
z
nil
50
(defun cx (c)
(car c))
(defun cy (c)
(car (cdr c)))
(defun cz (c)
(car (cdr (cdr c))))
4.7
A Notao de Lista
Reparemos que, medida que fomos aplicando sucessivamente a funo cdr, a lista foi encolhendo, i.e., fomos acedendo a partes sucessivamente mais pequenas da lista. No limite, quando aplicmos o cdr lista
(3) que j s tinha um elemento, estaramos espera de obter a lista vazia
(), i.e, a lista sem quaisquer elementos mas, no seu lugar, obtivmos nil.
Tal deve-se ao facto de as listas do Lisp serem apenas um artifcio de visualizao sobre um arranjo particular de pares e, na realidade, a operao
cdr continua a fazer o que sempre fez: acede ao segundo elemento do par
que, no caso de uma lista com um s elemento apenas a constante nil.
Por este motivo, para alm de representar o vazio, usual considerar que a
constante nil tambm representa a lista vazia.
Tal como as funes car e cdr podem ser vistas como operaes sobre
listas, tambm a funo cons o pode ser. Reparemos na seguinte interaco:
_$ (cons 1 nil)
(1)
_$ (cons 1 (cons 2 nil))
(1 2)
_$ (cons 1 (cons 2 (cons 3 nil)))
(1 2 3)
52
Como evidente, uma expresso da forma (list e1 e2 ... en ) absolutamente idntica a (cons e1 (cons e2 (... (cons en nil) ...))).
Obviamente, quando recebe zero argumentos a funo list produz
uma lista vazia:
_$ (list)
nil
Exerccio 4.7.1 Qual o significado da expresso (list (list))?
Exerccio 4.7.2 Quantos elementos tem a lista resultante de (list (list (list)))?
Exerccio 4.7.3 Qual o significado da expresso (cons (list 1 2) (list 3 4))?
4.8
tomos
Vimos que os pares (e as listas) permitem-nos criar aglomeraes de elementos e que podemos posteriormente aceder aos componentes dessas aglomeraes usando as operaes car e cdr. De facto, atravs de combinaes de cars e cdrs conseguimos aceder a qualquer elemento que faa
parte da aglomerao.
O que no possvel, contudo, usar car ou cdr para aceder ao interior de um desses elementos. Por exemplo, no possvel, usando as operaes car ou cdr, aceder a um carcter qualquer dentro de uma string.
Por este motivo, as strings dizem-se atmicas, i.e., no decomponveis. Os
nmeros, obviamente, tambm so atmicos.
Sendo uma lista uma aglomerao de elementos, natural pensar que
uma lista no atmica. Contudo, h uma lista em particular que merece
53
um pouco mais de ateno: a lista vazia. Uma lista vazia no decomponvel pois, de facto no contm nenhum elemento que se possa obter usando
o car nem nenhuns restantes elementos que se possam obter usando o
cdr.14 Se no se pode usar nem o car nem o cdr, isso sugere que a lista
vazia , na realidade, um tomo e, de facto, o Auto Lisp assim o considera.
O facto de a lista vazia ser, simultaneamente, um tomo e uma lista provoca um aparente paradoxo na definio de atomicidade pois faz com que
exista uma listaa lista vaziaque aparenta ser simultaneamente atmica
e no atmica. No entanto, o parodoxo apenas aparente pois, na realidade, a definio de atomicidade apenas exclui pares. Uma vez que a lista
vazia no um par, ela atmica, embora seja uma lista.15
Exerccio 4.8.1 Classifique, quanto atomicidade, o resultado da avaliao das seguintes
expresses:
1. (cons 1 2)
2. (list 1 2)
3. (strcat "Bom" " " "Dia")
4. nil
5. (+ 1 2 3)
6. (list 1)
7. (list)
8. (car (cons 1 (cons 2 nil)))
9. (cdr (cons 1 (cons 2 nil)))
4.9
Tipos Abstractos
Na realidade, alguns dialectos de Lisp, incluindo o Auto Lisp, consideram que possvel aplicar as funes car e cdr lista vazia, obtendo-se, em ambos os casos, a lista vazia.
15
Nesta matria, a documentao do Auto Lisp est simplesmente incorrecta pois afirma
que tudo o que no for uma lista um tomo, esquecendo-se de excluir a lista vazia que,
obviamente, uma lista mas tambm um tomo.
54
mudmos de um particular arranjo de pares para outro, possvel alterarmos a representao de um tipo abstracto sem afectar os programas que
usam o tipo abstracto.
Um tipo abstracto caracterizado apenas pelas suas operaes e estas
podem ser divididas em dois conjuntos fundamentais: os construtores que,
a partir de argumentos de tipos apropriados, produzem elementos do tipo
abstracto, e os selectores que, a partir de um elemento do tipo abstracto, produzem os seus constituintes. Existem ainda outras categorias de operaes
mas, por agora iremos concentrarmo-nos apenas nestas duas.
No caso das coordenadas cartesianas tri-dimensionais, o conjunto dos
construtores apenas contm a funo xyz, enquanto que o conjunto dos selectores contm as funes cx, cy e cz. Para um tipo abstracto, a relao
entre os construtores e os selectores crucial pois eles tm de ser consistentes entre si. Matematicamente, essa consistncia assegurada por equaes
que, no caso presente, se podem escrever da seguinte forma:
(cx (xyz x y z)) = x
(cy (xyz x y z)) = y
(cz (xyz x y z)) = z
Se modificarmos a representao de coordenadas mas mantivermos a
consistncia entre os construtores e os selectores, manter-se- tambm o
correcto funcionamento do tipo abstracto. Foi por este motivo que nos foi
possvel refazer a implementao das coordenadas bi- e tri-dimensionais
sem afectar as funes j definidas +xy, distancia-2d e distancia-3d.
Exerccio 4.9.1 O que um construtor de um tipo abstracto?
Exerccio 4.9.2 O que um selector de um tipo abstracto?
Exerccio 4.9.3 O que a representao de um tipo abstracto?
Exerccio 4.9.4 Dado um ponto P0 = (x0 , y0 ) e uma recta definida por dois pontos P1 =
(x1 , y1 ) e P2 = (x2 , y2 ), a distncia mnima d do ponto P0 recta obtm-se pela frmula:
d=
55
4.10
Coordenadas em AutoCad
56
usando directamente as operaes do tipo lista, i.e., construindo coordenadas com a funo list e acedendo aos seus valores com as funes car,
cadr e caddr. Acontece que esta violao do tipo abstracto ocorre, actualmente, muito mais por razes histricas do que por razes de performance.
Embora sejamos grandes defensores do respeito pragmtica do Auto
Lisp, neste caso particular vamos adoptar uma abordagem diferente: por
motivos de clareza dos programas, de facilidade da sua compreenso e de
facilidade da sua correco, vamos empregar as operaes do tipo abstracto
coordenadas, nomeadamente os construtores xy e xyz e os selectores cx,
cy e cz e vamos evitar, sempre que possvel, aceder directamente representao das coordenadas, i.e., vamos evitar usar as funes list, car,
cadr e caddr para manipular coordenadas. Isso no impede que usemos
essas funes para outros fins, em particular, para manipular listas. Uma
vez que as coordenadas esto implementadas usando listas, esta distino
poder parecer confusa mas, na verdade, no : as coordenadas no so
listas embora a representao das coordenadas seja uma lista.
Naturalmente, quando o leitor consultar programas escritos por outros
programadores de Auto Lisp dever ter em conta estas subtilezas e dever
conseguir perceber se uma dada lista presente num programa significa coordenadas ou se significa outro tipo abstracto qualquer.
4.11
Coordenadas Polares
57
x
Figura 6: Coordenadas rectangulares e polares.
p
= x2 + y 2
= arctan y
x
Com base nas equaes anteriores, podemos agora definir a funo pol
(abreviatura de polar) que contri coordenadas a partir da sua representao polar simplesmente convertendo-a para a representao rectangular
equivalente.
(defun pol (ro fi)
(xy (* ro (cos fi))
(* ro (sin fi))))
58
P0
relativamente evidente que a funo +pol est a fazer parte do trabalho que j feito pela funo +xy, nomeadamente no que diz respeito
soma das coordenadas do ponto p com as componentes que resultam da
converso de coordenadas polares para rectangulares. Assim, possvel
simplificar a funo +pol escrevendo apenas:
(defun +pol (p ro fi)
(+xy p
(* ro (cos fi))
(* ro (sin fi))))
4.12
A funo command
P0
P0
P1
y
x
Figura 8: O deslocamento de um ponto por adio de um vector.
Existem trs maneiras diferentes de se invocar essas operaes grficas
mas, por agora, vamos explorar apenas a mais simples: a funo command.
A funo command aceita um nmero arbitrrio de expresses que vai
avaliando e passando os valores obtidos para o AutoCad medida que o
AutoCad os vai requerendo.18 No caso de utilizao mais comum, a funo command recebe uma cadeia de caracteres que descreve o comando
AutoCad que se pretende executar seguido de qualquer nmero de argumentos que sero usados como os dados necessrios para a execuo desse
comando.
A vantagem da funo command permitir criar programas completos
que criam entidades grficas tal como um normal utilizador de AutoCad o
poderia fazer de forma manual. A ttulo de exemplo, consideremos a criao de um crculo. Para se criar um crculo em AutoCad pode-se usar o
comando circle e fornecer-lhe as coordenadas do centro e o raio do crculo. Se pretenderemos criar o mesmo crculo a partir do Auto Lisp, ao
invs de invocarmos interactivamente o comando AutoCad circle e de
lhe fornecermos os dados necessrios, podemos simplesmente invocar a
funo command e passar-lhe todos os dados necessrios como argumentos, comeando pela string "circle", seguida das coordenadas do centro
do crculo e, por ltimo, seguida do raio do crculo.
Para concretizarmos o exemplo, consideremos a criao de um crculo
de raio r = 1 centrado na posio (x, y) = (2, 3). A invocao Auto Lisp
18
61
importante memorizar esta ltima expresso pois, sem a sua invocao, todos os usos da funo command estaro sob o efeito de Object Snaps,
fazendo com que as coordenadas que indicamos para as nossas figuras geomtricas no sejam estritamente respeitadas pelo AutoCad, que as arredondar de acordo com a malha do Object Snaps.
62
64
Finalmente, sabemos que depois desta interaco, o AutoCad vai continuar espera que indiquemos que terminmos a seleco de objectos atravs do premir da tecla enter, o que implica que temos de indicar funo
command para simplesmente passar o tal premir virtual da tecla enter.
Ora j sabemos que a funo faz isso automaticamente aps passar os caracteres de uma string pelo que, se no queremos passar caracteres alguns
mas apenas a tecla enter ento, logicamente, temos de usar uma string
vazia, ou seja:
(command "erase" "all" "")
Como se pode constatar pelo exemplo anterior, a funo command termina assim que conseguir passar todos os argumentos que tem para o AutoCad, independentemente de eles serem suficientes ou no para o AutoCad conseguir completar o pretendido. Se no forem, o AutoCad limita-se
a continuar espera que lhe forneamos, via command ou directamente na
interface, os dados que lhe faltam, o que nos permite implementar um processo de colaborao com o AutoCad: parte do que se pretende feito no
lado do Auto Lisp e a parte restante no lado do AutoCad.
Por exemplo, imaginemos que pretendemos criar um crculo num dado
ponto mas queremos deixar ao utilizador a escolha do raio. Uma soluo
65
Um outro aspecto importante da funo command prende-se com a passagem de nmeros e coordenadas (representadas por listas de nmeros).
Embora nos exemplos anteriores estes tipos de dados tenham sido directamente passadas funo command, na realidade tambm podem ser passados simulando o premir das teclas correspondentes. Isto quer dizer que
possvel criar um crculo com centro no ponto (2, 3) e raio 1 atravs da
expresso:
(command "circle" "2,3" "1")
66
Escreva uma sequncia de expresses que, quando avaliadas, produzem a figura anterior.
Exerccio 4.12.5 Pretendemos colocar quatro circunferncias de raio unitrio em torno da
origem de modo a que fiquem encostadas umas s outras, tal como se ilustra no seguinte
desenho:
Escreva uma sequncia de expresses que, quando avaliadas, produzem a figura anterior.
Exerccio 4.12.6 Pretendemos colocar trs circunferncias de raio unitrio em torno da origem de modo a que fiquem encostadas umas s outras, tal como se ilustra no seguinte
desenho:
Escreva uma sequncia de expresses que, quando avaliadas, produzem a figura anterior.
67
4.13
Variantes de Comandos
68
4.14
ngulos em Comandos
69
polygon necessita de saber quantos lados ele dever ter, qual o centro do
polgono, se ele vai estar inscrito numa circunferncia ou circunscrito numa
circunferncia e, finalmente o raio dessa circunferncia e o ngulo que o
primeiro vrtice do polgono faz com o eixo dos x. Este dois ltimos
parmetros, contudo, no podem ser fornecidos separadamente, sendo necessrio especific-los de uma forma conjunta, atravs de uma string em
que se junta o raio e o ngulo separados pelo carcter < (representando
um ngulo) e precedidos do carcter @ (representando um incremento
relativamente ao ltimo ponto dado, que era o centro da circunferncia).
Por exemplo, o raio 2 com um ngulo de 30o escreve-se "@2<30". Note-se
que o ngulo tem de estar em graus. Se, ao invs de fornecermos esta string
fornecermos apenas um nmero, o AutoCad ir tratar esse nmero como o
raio e, mesmo que lhe tentemos fornecer outro nmero para o ngulo, ir
assumir que o ngulo zero.
Uma vez que, na maior parte dos casos, os raios e ngulos sero parmetros das nossas funes e ainda que, do ponto de vista matemtico,
prefervel trabalhar em radianos, conveniente definir uma funo que,
a partir do raio e ngulo em radianos, produz a string apropriada com o
ngulo em graus. Para isso, conveniente usarmos a funo strcat para
concatenarmos as strings parciais que sero produzidas atravs da funo
rtos que converte um nmero numa string. Assim, temos:
(defun raio&angulo (raio angulo)
(strcat "@"
(rtos raio)
"<"
(rtos (graus<-radianos angulo))))
(raio&angulo 1 0))
(raio&angulo 1 (/ pi 3)))
(raio&angulo 1 0))
(raio&angulo 1 (/ pi 4)))
(raio&angulo 1 0))
(raio&angulo 1 (/ pi 5)))
70
4.15
Efeitos Secundrios
Vimos anteriormente que qualquer expresso Lisp tem um valor. No entanto, aquilo que se pretende de uma expresso que use a funo command
no saber qual o seu valor mas sim qual o efeito que produzido num
determinado desenho. De facto, a execuo de um comando AutoCad produz, em geral, uma alterao do desenho actual, sendo irrelevante o seu
valor.
Este comportamento da funo command fundamentalmente diferente
do comportamento das funes que vimos at agora pois, anteriormente,
as funes eram usadas para computar algo, i.e., para produzir um valor
a partir da sua invocao com determinados argumentos e, agora, no o
valor que resulta da invocao do comando que interessa mas sim o efeito
secundrio (tambm chamado efeito colateral) que interessa.
Contudo, mesmo no caso em que apenas nos interessa o efeito secundrio, necessrio continuar a respeitar a regra de que, em Lisp, qualquer
expresso tem um valor e, por isso, tambm uma invocao de funo
tem de produzir um valor como resultado. por este motivo que a invocao da funo command devolve sempre nil como resultado. Obviamente que qualquer outro valor serviria (pois no suposto ser usado)
mas convenciona-se que nos casos em que no h um valor mais relevante
a devolver deve-se devolver nil (que, em Latim, significa nada).22
22
71
Tendo em conta a interaco anterior, defina uma funo Auto Lisp denominada tronco-cone
cujos parmetros so o ponto P do centro da base do slido, a altura h do slido e os raios
rb e rt da base e do topo do slido e que cria o tronco de cone correspondente em AutoCad.
4.16
A Ordem Drica
23
Estas colunas apresentam ainda uma deformao intencional denominada entasis. A
entasis consiste em dar uma ligeira curvatura coluna e, segundo alguns autores, destinase a corrigir uma iluso de ptica que faz as colunas direitas parecerem encurvadas.
72
73
(1, 11)
(1, 11)
(1, 10.5)
(1, 10.5)
(0.8, 10)
(0.8, 10)
x
(1, 0) (0, 0) (1, 0)
No caso do baco, podemos empregar uma abordagem idntica ou podemos explorar outro comando do AutoCad ainda mais simples destinado
construo de rectngulos. Este comando apenas necessita de dois pontos
para definir completamente o rectngulo:
(defun abaco ()
(command "_.rectangle"
(xy -1 10.5)
(xy 1 11)))
75
Repare-se, na funo coluna, que ela invoca sequencialmente as funes fuste, coxim e, finalmente, abaco. Para percebermos o funcionamento da funo coluna importante saber que quando invocamos uma
funo que possui uma sequncia de expresses, o Lisp avalia sequencialmente cada uma das expresses, descartando o seu valor, at chegar
ltima cujo valor usado como valor final da funo. O facto de se descartarem todos os valores excepto o ltimo mostra que, numa sequenciao
de expresses, o que importa o efeito secundrio da sua avaliao. A
sequenciao o exemplo mais simples de uma estrutura de controle. Em
termos muito grosseiros, uma estrutura de controle um mecanismo das
linguagens de programao que indica ao computador a ordem pela qual
pretendemos que ele execute o programa.
A Figura 14 mostra o resultado da invocao da funo coluna.
4.17
rt
P1 = (x rt , y + a)
P2 = (x + rt , y + a)
P = (x, y)
P4 = (x rb , y)
rb
P3 = (x + rb , y)
77
rt
P2 = (x rt , y + a)
P = (x, y)
P1 = (x rb , y)
rb
P3 = (x + rt , y + a)
a
P4 = (x + rb , y)
78
P2 = (x + 2l , y + a)
P = (x, y)
P1 = (x 2l , y)
Com base nestas funes, podemos agora facilmente experimentar variaes de colunas. As seguintes invocaes produzem o desenho apresentado na Figura 19.
79
la
rbc
aa
ac
af
rbf
80
(xy 0 0)
(xy 3 0)
(xy 6 0)
(xy 9 0)
(xy 12 0)
(xy 15 0)
9
7
9
8
5
6
0.5
0.5
0.7
0.4
0.5
0.8
0.4
0.4
0.5
0.3
0.4
0.3
0.3
0.6
0.3
0.2
0.3
0.2
0.3
0.6
0.2
0.3
0.1
0.4
1.0)
1.6)
1.2)
1.0)
1.0)
1.4)
Como bvio pela anlise desta figura, nem todas as colunas desenhadas obedecem aos cnones da ordem Drica. Mais frente iremos ver que
modificaes sero necessrias para evitar este problema.
4.18
Documentao
81
82
a-fuste r-base-fuste
a-coxim r-base-coxim
a-abaco l-abaco)
;;desenhamos o fuste com a base em p
(fuste p a-fuste r-base-fuste r-base-coxim)
;;colocamos o coxim por cima do fuste
(coxim (+y p a-fuste) a-coxim r-base-coxim (/ l-abaco 2.0))
;;e o abaco por cima do coxim
(abaco (+y p (+ a-fuste a-coxim)) a-abaco l-abaco))
Desta forma, quem for ler o nosso programa fica com uma ideia muito
mais clara do que cada funo faz, sem sequer precisar de ir estudar o corpo
das funes. Como se v pelo exemplo anterior, pragmtica usual em
Lisp usar um diferente nmero de caracteres ; para indicar a relevncia
do comentrio:
;;;; Devem comear na margem esquerda e servem para dividir o programa em seces e dar um ttulo a cada seco.
;;; Devem comear na margem esquerda e servem para fazer comentrios gerais ao programa que aparece em seguida. No se devem usar
no interior das funes.
;; Devem estar alinhadas com a parte do programa a que se vo aplicar,
que aparece imediatemente em baixo.
; Devem aparecer alinhados numa mesma coluna direita e comentam a
parte do programa imediatamente esquerda.
importante que nos habituemos a documentar as nossas definies
mas convm salientar que a documentao em excesso tambm tem desvantagens:
O cdigo Lisp deve ser suficientemente claro para que um ser humano o consiga perceber. sempre prefervel perder mais tempo a
tornar o cdigo claro do que a escrever documentao que o explique.
Documentao que no est de acordo com o programa pior que
no ter documentao.
frequente termos de modificar os nossos programas para os adaptar
a novos fins. Quanto mais documentao existir, mais documentao
necessrio alterar para a pr de acordo com as alteraes que tivermos feito ao programa.
83
N
O desenho deve ainda obedecer s seguintes propores:
O ngulo de abertura da seta de 45 .
O comprimento da farpa de 2 .
O centro da letra N dever ser posicionado a uma distncia de
da seta segundo a direco da seta.
10
da extremidade
84
(divisao-rectangular
(divisao-rectangular
(divisao-rectangular
(divisao-rectangular
(divisao-rectangular
(divisao-rectangular
(xy
(xy
(xy
(xy
(xy
(xy
0
4
6
0
5
8
0)
0)
0)
5)
5)
3)
4
2
5
5
3
3
3
3
3
4
4
6
"cozinha")
"despensa")
"quarto")
"sala")
"i.s.")
"quarto")
4.19
Depurao
Como sabemos, errare humanum est. O erro faz parte do nosso dia-a-dia e,
por isso, em geral, sabemos lidar com ele. J o mesmo no se passa com
as linguagens de programao. Qualquer erro num programa tem, como
consequncia, que o programa tem um comportamento diferente daquele
que era esperado.
Uma vez que fcil cometer erros, deve tambm ser fcil detect-los
e corrigi-los. actividade de deteco e correco de erros denomina-se
depurao. Diferentes linguagens de programao providenciam diferentes mecanismos para essa actividade. Neste domnio, como iremos ver, o
AutoCad est particularmente bem apetrechado.
Em termos gerais, os erros num programa podem classificar-se em erros
sintticos e erros semnticos.
4.19.1
Erros Sintticos
O erro de que o Auto Lisp nos est a avisar de que a forma defun que
lhe demos para avaliar no obedece sintaxe exigida para essa forma e, de
facto, uma observao atenta da forma anterior mostra que no seguimos a
sintaxe exigida para uma definio e que, tal como discutimos na seco 3.6,
era a seguinte:
(defun nome (parmetro1 ... parmetron )
corpo)
Nem todos os dialectos e interpretadores de Lisp possuem exactamente este comportamento mas, variaes parte, os conceitos so os mesmos.
86
4.19.2
Erros Semnticos
Os erros semnticos so muito diferentes dos sintticos. Um erro semntico no um erro na escrita de uma frase da linguagem mas sim um
erro no significado dessa frase. Dito de outra forma, um erro semntico
ocorre quando escrevemos uma frase que julgamos ter um significado e, na
verdade, ela tem outro.
Em geral, os erros semnticos apenas so detectveis durante a invocao das funes que os contm. Parte dos erros semnticos detectvel
pelo avaliador de Lisp mas h inmeros erros cuja deteco s pode ser
feita pelo prprio programador.
Como exemplo de erro semntico consideremos uma operao sem significado como seja a soma de um nmero com uma string:
_$ (+ 1 "dois")
; error: bad argument type: numberp: "dois"
Como podemos ver pela resposta, o Auto Lisp protesta que um dos argumentos devia ser um nmero mas, em lugar disso, era nil. Uma vez
que a funo coluna-standard no tem quaisquer argumentos, a mensagem de erro poder ser difcil de compreender. No entanto, ela torna-se
compreensvel quando pensamos que o erro poder no ter ocorrido na invocao da funo coluna-standard mas sim em qualquer funo que
tenha sido invocada directa ou indirectamente por esta.
27
Consegue detect-lo?
87
:ERROR-BREAK
(+ nil -0.3)
(+XY (nil 0) -0.3 9)
(FUSTE (nil 0) 9 0.5 0.3)
(COLUNA (nil 0) 9 0.5 0.4 0.3 0.3 0.5)
(COLUNA-STANDARD)
88
(defun coluna-standard ()
(coluna (xy O 0) 9 0.5 0.4 0.3 0.3 0.5))
Acontece que, em Auto Lisp, qualquer nome que no tenha sido previamente definido tem o valor nil e, como o nome constitudo pela letra O
no est definido, a avaliao do primeiro argumento da funo xy , na
verdade, nil. Esta funo, como se limita a fazer uma lista com os seus
argumentos, cria uma lista cujo primeiro elemento nil e cujo segundo
elemento zero. A lista resultante assim passada de funo em funo
at chegarmos funo +xy que, ao tentar fazer a soma, acaba por provocar o erro.
Esta sesso de depurao mostra o procedimento habitual para deteco de erros. A partir do momento em que o erro identificado, geralmente fcil corrigi-lo mas convm ter presente que o processo de identificao de erros pode ser moroso e frustrante. tambm um facto que
a experincia de deteco de erros extremamente til e que, por isso,
expectvel que enquanto essa experincia for reduzida, o processo de deteco seja mais lento.
Modelao Tridimensional
5.1
As verses mais recentes do AutoCad disponibilizam um conjunto de operaes pr-definidas que constroem um slido a partir da especificao das
suas coordenadas tridimensionais. Embora as operaes pr-definidas apenas permitam construir um conjunto muito limitado de slidos, esse conjunto suficiente para a elaborao de modelos sofisticados.
89
Para se conhecer as especificidades de cada comando recomenda-se a consulta da documentao que acompanha o AutoCad.
31
A construo de uma pirmide exige a especificao simultnea do raio e ngulo da
base. Tal como explicado na seco 4.14, a funo raio&angulo constri essa especificao
a partir dos valores do raio e do ngulo.
90
Usando esta funo agora mais simples definir outras estruturas mais
complexas. Por exemplo, uma cruz papal define-se pela unio de trs cilindros horizontais de comprimento progressivamente decrescente dispostos
ao longo de um cilindro vertical, tal como se pode ver na Figura 21. de
salientar que os cilindros tm todos o mesmo raio e que o seu comprimento
e posicionamento funo desse raio. Em termos de proporo, o cilindro
vertical da cruz papal tem um comprimento igual a 20 raios, enquanto que
os cilindros horizontais possuem comprimentos iguais a 14, 10 e 6 raios
91
(p raio)
p 0 0 (* 20 raio)))
p (* -7 raio) 0 (* 9 raio))
p (* +7 raio) 0 (* 9 raio)))
p (* -5 raio) 0 (* 13 raio))
p (* +5 raio) 0 (* 13 raio)))
p (* -3 raio) 0 (* 17 raio))
p (* +3 raio) 0 (* 17 raio))))
3
5
4
6
7
(xyz 0 0
(xyz -2 0
(xyz 0 2
(xyz 2 0
(xyz 0 -2
0)
0)
0)
0)
0)
0.4
0.4
0.4
0.4
0.4
0
0
0
0
0
(xyz 0 0 5))
(xyz -1 1 5))
(xyz 1 1 5))
(xyz 1 -1 5))
(xyz -1 -1 5))
93
5.2
Finalmente, no que diz respeito ao bacoo paralelippedo que colocado no topo da colunatemos vrias maneiras de o especificarmos. A
mais directa consiste em indicar os dois cantos do paralelippedo. Uma outra, menos directa, consiste em indicar o centro do paralelippedo seguido
do tamanho dos seus lados. Por agora, vamos seguir a mais directa:
(defun abaco (p a-abaco l-abaco)
(command "_.box"
(+xyz p (/ l-abaco -2.0) (/ l-abaco -2.0) 0)
(+xyz p (/ l-abaco +2.0) (/ l-abaco +2.0) a-abaco)))
Exerccio 5.2.1 Implemente a funo abaco mas empregando a criao de um paralelippedo centrado num ponto seguido da especificao do seu comprimento, largura e altura.
95
(xyz 0 0
(xyz 3 0
(xyz 6 0
(xyz 9 0
(xyz 12 0
(xyz 15 0
0)
0)
0)
0)
0)
0)
9
7
9
8
5
6
0.5
0.5
0.7
0.4
0.5
0.8
0.4
0.4
0.5
0.3
0.4
0.3
0.3
0.6
0.3
0.2
0.3
0.2
0.3
0.6
0.2
0.3
0.1
0.4
1.0)
1.6)
1.2)
1.0)
1.0)
1.4)
A partir deste modelo, agora trivial usarmos as capacidades do AutoCad para extrair qualquer vista que pretendamos, incluindo perspectivas
como a que apresentamos na Figura 24.
Expresses Condicionais
Existem muitas operaes cujo resultado depende da realizao de um determinado teste. Por exemplo, a funo matemtica |x|que calcula o valor
absoluto de um nmeroequivale ao prprio nmero, se este positivo,
ou equivale ao seu simtrico se for negativo. Esta funo ter, portanto de
96
97
6.1
Expresses Lgicas
Desta forma, reduzimos todos os testes a expresses cujo valor pode ser
apenas um de dois, e a expresso condicional assume a forma de se . . . ento
. . . caso contrrio . . . . A expresso cujo valor usado para decidir se devemos usar o ramo ento ou o ramo caso contrrio denomina-se expresso
lgica e caracteriza-se por o seu valor ser interpretado como verdade ou falso.
Por exemplo, a expresso lgica (> x y) testa se o valor de x maior que
o valor de y. Se for, a expresso avalia para verdade, caso contrrio avalia
para falso.
6.2
Valores Lgicos
6.3
Predicados
No caso mais usual, uma expresso lgica uma invocao de funo com
determinados argumentos. Nesta situao, a funo usada como teste
denominada predicado e o valor do teste interpretado como sendo verdadeiro ou falso. O predicado , consequentemente, uma funo que devolve
apenas verdade ou falso.
32
98
Apesar da adopo dos smbolos t e nil, convm alertar que nem todos os predicados devolvem t ou nil exclusivamente. Alguns h que,
quando querem indicar verdade, devolvem valores diferentes de t (e de
nil, obviamente).
6.4
Predicados Aritmticos
Os operadores relacionais matemticos <, >, =, , e 6= so um dos exemplos mais simples de predicados. Estes operadores comparam nmeros
entre si e permitem saber se um nmero menor que outro. O seu uso em
Lisp segue as regras da notao prefixa e escrevem-se, respectivamente, <,
>, =, <=, >= e /=. Eis alguns exemplos:
_$ (> 4 3)
t
_$ (< 4 3)
nil
_$ (<= (+ 2 3) (- 6 1))
t
6.5
Operadores Lgicos
99
6.6
Uma propriedade importante dos predicados aritmticos <, >, =, <=, >= e
/= aceitarem qualquer nmero de argumentos. No caso em que h mais
do que um argumento, o predicado aplicado sequencialmente aos pares
de argumentos. Assim, (< e1 e2 e3 ... en1 en ) equivalente a escrever (and (< e1 e2 ) (< e2 e3 ) ... (< en1 en )). Este comportamento
visvel nos sequintes exemplos.
_$ (< 1 2 3)
T
_$ (< 1 2 2)
nil
Um caso particular que convm ter em ateno que embora a expresso (= e1 e2 ... en ) teste se os elementos e1 e2 . . . en so todos iguais,
(/= e1 e2 ... en ) no testa se os elementos e1 e2 . . . en so todos diferentes: uma vez que o teste aplicado sucessivamente a pares de elementos
perfeitamente possvel que existam dois elementos iguais desde que no
sejam consecutivos. Esse comportamento visvel no seguinte exemplo:33
_$ (/= 1 2 3)
T
_$ (/= 1 2 1)
T
6.7
100
6.8
"pois" "pois")
"pois" "poisar")
"pois" "poisar")
"abcd" "abce")
6.9
Vimos que os dados manipulados pelo Lisp se podiam classificar em atmicos ou no-atmicos consoante era impossvel, ou no, aplicar-lhes as
operaes de listas car e cdr.
Para facilitar a identificao das entidades atmicos, a linguagem Lisp
disponibiliza uma funo denominada atom que s verdadeira para as
entidades atmicas:
_$ (atom
T
_$ (atom
T
_$ (atom
T
_$ (atom
nil
_$ (atom
nil
1)
"dois")
quatro)
(cons 1 "dois"))
(list 1 "dois" 3.0))
101
_$ (atom ())
T
_$ (atom t)
T
_$ (atom nil)
T
6.10
Reconhecedores
102
6.11
Reconhecedores Universais
Um outro conjunto importante de predicados so os denominados reconhecedores universais. Estes no reconhecem elementos particulares de um tipo
de dados mas sim todos os elementos de um particular tipo de dados. Um
reconhecedor universal aceita qualquer tipo de valor como argumento e
devolve verdade se o valor do tipo pretendido.
Por exemplo, para sabermos se uma determinada entidade um nmero podemos empregar o predicado numberp:34
_$ (numberp 1)
T
_$ (numberp nil)
nil
_$ (numberp "Dois")
nil
Para testar se uma determinada entidade uma lista podemos empregar o predicado listp. Este predicado verdade para qualquer lista (incluindo a lista vazia) e falso para tudo o resto:
_$ (listp
T
_$ (listp
nil
_$ (listp
T
_$ (listp
T
(list 1 2))
1)
(list))
(cons 1 2))
Note-se, no ltimo exemplo, que o reconhecedor universal listp tambm considera como lista um mero par de elementos. Na realidade, este
reconhecedor devolve verdade sempre que o seu argumento um dotted
pair ou o nil. As listas, como vimos, no so mais do que arranjos particulares de dotted pairs ou, no limite, uma lista vazia.
34
tradicional, em vrios dialectos de Lisp, terminar o nome dos predicados com a letra
p. Noutros dialectos, prefere-se terminar esse nome com um ponto de interrogao precisamente porque, na prtica, a invocao de um predicado corresponde a uma pergunta que
fazemos. Neste texto, nos casos em que fizer sentido enquadrarmo-nos com a tradio, iremos empregar a letra p; em todos os outros casos iremos empregar o ponto de interrogao.
103
Para a maioria dos tipos, o Auto Lisp no providencia nenhum reconhecedor universal, antes preferindo usar a funo genrica type que devolve
o nome do tipo como smbolo. Como vimos na secco 3.14, temos:
_$ (type
REAL
_$ (type
INT
_$ (type
STR
_$ (type
USUBR
_$ (type
SUBR
pi)
1)
"Ola")
quadrado)
+)
igualmente trivial definir um reconhecedor universal de strings e outro para funes (compiladas ou no):
(defun stringp (obj)
(= (type obj) str))
(defun functionp (obj)
(or (= (type obj) subr)
(= (type obj) usubr)))
6.12
Exerccios
Exerccio 6.12.1 O que uma expresso condicional? O que uma expresso lgica?
Exerccio 6.12.2 O que um valor lgico? Quais so os valores lgicos empregues em Auto
Lisp?
Exerccio 6.12.3 O que um predicado? D exemplos de predicados em Auto Lisp.
Exerccio 6.12.4 O que um operador relacional? D exemplos de operadores relacionais
em Auto Lisp.
104
Exerccio 6.12.5 O que um operador lgico? Quais so os operadores lgicos que conhece
em Auto Lisp?
Exerccio 6.12.6 O que um reconhecedor? O que um reconhecedor universal? D exemplos em Auto Lisp.
Exerccio 6.12.7 Traduza para Lisp as seguintes expresses matemticas:
1. x < y
2. x y
3. x < y y < z
4. x < y x < z
5. x y z
6. x y < z
7. x < y z
Estruturas de Controle
7.1
Sequenciao
106
_$ (progn
(+ 1 2)
(* 3 4))
12
Este operador recebe vrias expresses como argumento que avalia sequencialmente, devolvendo o valor da ltima. Quando definimos uma funo todas as expresses que colocamos no corpo da funo so avaliadas
num progn implcito. Como iremos ver, existem ainda outras formas da
linguagem Lisp que possuem progns implcitos.35
7.2
Invocao de Funes
O nome progn parece pouco intuitivo mas, como a maioria dos nomes usados em
Lisp, tem uma histria que o justifica. Os Lisps originais disponibilizavam um operador
denominado prog (abreviatura de program) que, entre vrias outras coisas, permitia
sequenciao. Para alm deste operador, foram introduzidas variantes mais simples, denominadas prog1que avaliava sequencialmente os seus argumentos e retornava o valor da
primeira, prog2que avaliava sequencialmente os seus argumentos e retornava o valor
da segundae, finalmente, prognque avaliava sequencialmente os seus argumentos e
retornava o valor da ltima. Apenas este ltimo operador foi implementado em Auto Lisp.
107
Para que o avaliador de Lisp consiga avaliar a ltima combinao necessita de comear por avaliar todos os seus elementos. O primeiro, o
smbolo +, avalia para o procedimento que realiza somas mas, antes de
poder fazer a soma, precisa de determinar os seus argumentos atravs da
avaliao dos restantes elementos da combinao. O primeiro argumento
o nmero 1 pois, como vimos anteriormente, o valor de um nmero
o prprio nmero. Depois de avaliar o primeiro argumento, o avaliador
depara-se com uma nova combinao. Nesse momento, suspende a avaliao que estava a fazer e inicia uma nova avaliao, agora para a combinao
(quadrado 2). Novamente, porque se trata da aplicao de uma funo,
o avaliador vai avaliar todos os seus argumentos que, neste caso, apenas
um nmero que avalia para ele prprio. A partir deste momento, o controle
transferido para o corpo da funo quadrado, mas fazendo a associao
do parmetro x ao valor 2. A avaliao do corpo da funo quadrado implica a avaliao da combinao (* x x). Trata-se de uma multiplicao
cujos argumentos so obtidos pela repetida avaliao do smbolo x. Uma
vez que a invocao da funo tinha associado x ao argumento 2, o valor
de x 2. No entanto, para realizar a multiplicao necessrio ter em conta
que se trata, mais uma vez, da invocao de uma funo, pelo que a avaliao da invocao da funo quadrado por sua vez suspensa para se
passar avaliao da multiplicao. No instante seguinte, a multiplicao
realizada e tem como resultado o nmero 4. Nesse momento, o avaliador
termina a invocao da multiplicao e faz o controle regressar avaliao do quadrado de 2. Uma vez que a multiplicao a ltima expresso
da funo quadrado, esta invocao vai tambm terminar tendo como resultado o mesmo da multiplicao, i.e., 4. Mais uma vez, o avaliador vai
transferir o controle, agora para a expresso que estava a avaliar quando
invocou a funo quadrado, avaliando o ltimo argumento da soma (que
avalia para ele prprio), permitindo-lhe assim concluir a soma com o valor
8.
Resumidamente, a invocao de funes consiste em suspender a
avaliao que se estava a fazer para (1) se associarem os argumentos da invocao aos parmetros da funo invocada, (2) avaliar o corpo da funo
tendo aquela associao em conta e (3) retomar a avaliao suspendida
108
7.3
Variveis Locais
a
e tentemos definir uma funo Auto Lisp que calcula a rea do tringulo a
partir dos parmetros a, b e c.
Uma das formas de calcular a rea do tringulo baseia-se na famosa
frmula de Heron:36
A=
s (s a) (s b) (s c)
a+b+c
2
36
109
c)
2) a)
2) b)
2) c))))
Na definio anterior h dois aspectos novos que vamos agora discutir: a declarao da varivel local s e a atribuio dessa varivel atravs do
operador setq.
Para se indicar que uma funo vai usar variveis locais, estas tm de
ser declaradas conjuntamente com a lista de parmetros da funo. Para
isso, vamos agora ampliar a sintaxe da definio de funes que apresentmos anteriormente (na seco 3.6 de modo a incorporar a declarao de
variveis locais:
110
7.4
Atribuio
Para alm da declarao de uma varivel local ainda necessrio atribuirlhe um valor, i.e., realizar uma operao de atribuio. Para isso, o Auto
Lisp disponibiliza o operador setq, cuja sintaxe :
(setq varivel1 expresso1
...
varivelm expressom )
A semntica deste operador consiste simplesmente em avaliar a expresso expresso1 e associar o seu valor ao nome varivel1 , repetindo este
processo para todas as restantes variveis e valores.
A utilizao que fazemos deste operador na funo area-triangulo
fcil de compreender:
(defun area-triangulo (a b c / s)
(setq s (/ (+ a b c) 2))
(sqrt (* s (- s a) (- s b) (- s c))))
Ao invocarmos a funo area-triangulo, passando-lhe os argumentos correspondentes aos parmetros a, b e c, ela comea por introduzir um
novo nomesque vai existir apenas durante a invocao da funo. De
seguida, atribui a esse nome o valor que resultar da avaliao da expresso (/ (+ a b c) 2). Finalmente, avalia as restantes expresses do corpo
da funo. Na prtica, como se a funo dissesse: Sendo s = a+b+c
2 ,
p
calculemos s (s a) (s b) (s c).
111
b + b2 4ac
b b2 4ac
x=
x=
2a
2a
Dada a utilidade desta frmula, podemos estar interessados em definir
uma funo que, dados os coeficientes a, b e c da equao do segundo grau
nos devolve as suas duas raizes. Para isso, vamos devolver um par de
nmeros calculados usando as duas frmulas acima:
(defun raizes-equacao-segundo-grau (a b c)
(cons (/ (- (- b)
(sqrt (- (quadrado b) (* 4 a c))))
(* 2 a))
(/ (+ (- b)
(sqrt (- (quadrado b) (* 4 a c))))
(* 2 a))))
112
7.5
Variveis Globais
Na realidade, o Auto Lisp permite ainda uma terceira categoria de nomes que no so
nem locais, nem globais. Mais frente discutiremos esse caso.
113
A declarao de variveis globais mais simples que a das variveis locais: basta uma primeira atribuio, em qualquer ponto do programa, para
a varivel ficar automaticamente declarada. Assim, se quisermos introduzir uma nova varivel global, por exemplo, para definir a razo de ouro38
1+ 5
=
1.6180339887
2
basta-nos escrever:
(setq razao-de-ouro (/ (+ 1 (sqrt 5)) 2))
A partir desse momento, o nome razao-de-ouro pode ser referenciado em qualquer ponto dos programas.
importante referir que o uso de variveis globais deve ser restrito,
na medida do possvel, definio de constantes, i.e., variveis cujo valor
nunca muda como, por exemplo, pi. Outros exemplos que podem vir a ser
teis incluem 2*pi, pi/2, 4*pi e pi/4, bem como os seus simtricos, que
se definem custa de:
(setq 2*pi (* 2 pi))
(setq pi/2 (/ pi 2))
(setq 4*pi (* 4 pi))
(setq pi/4 (/ pi 4))
(setq -pi (- pi))
(setq -2*pi (- 2*pi))
(setq -pi/2 (- pi/2))
(setq -4*pi (- 4*pi))
(setq -pi/4 (- pi/4))
38
Tambm conhecida por proporo divina e nmero de ouro, entre outras designaes, e
abreviada por em homenagem a Fineas, escultor Grego responsvel pela construo do
Partnon onde, supostamente, usou esta proporo. A razo de ouro foi inicialmente introduzida por Euclides quando resolveu o problema de dividir um segmento de recta em
duas partes de tal forma que a razo entre o segmento de recta e a parte maior fosse igual
razo entre a parte maior e a menor. Se for a o comprimento do parte maior e b o da menor,
o problema de Euclides idntico a dizer que a+b
= ab . Daqui resulta que a2 ab b2 = 0
a
b b2 +4b2
ou que a =
= b 12 5 . A raiz que faz sentido , obviamente, a = b 1+2 5 e,
2
114
O facto de uma varivel global ser uma constante implica que a varivel atribuda uma nica vez, no momento da sua definio. Esse facto
permite-nos usar a varivel sabendo sempre qual o valor a que ela est associada. Infelizmente, por vezes necessrio usarmos variveis globais que
no so constantes, i.e., o seu valor muda durante a execuo do programa,
por aco de diferentes atribuies feitas em locais diferentes e em momentos diferentes. Quando temos variveis globais que so atribuidas em diversos pontos do nosso programa, o comportamento deste pode tornar-se
muito mais difcil de entender pois, na prtica, pode ser necessrio compreender o funcionamento de todo o programa em simultneo e no apenas
funo a funo, como temos feito. Por este motivo, devemos evitar o uso
de variveis globais que sejam atribuidas em vrios pontos do programa.
7.6
Variveis Indefinidas
115
Figura 25: Perspectiva da modelao tri-dimensional de colunas cujos parmetros foram escolhidos aleatoriamente. Apenas uma das colunas obedece
aos cnones da Ordem Drica.
7.7
Propores de Vitrvio
A modelao de colunas dricas que desenvolvemos na seco 5.2 permitenos facilmente construir colunas, bastando para isso indicarmos os valores
dos parmetros relevantes, como a altura e o raio da base do fuste, a altura e raio da base do coxim e a altura e largura do baco. Cada um destes
parmetros constitui um grau de liberdade que podemos fazer variar livremente.
Embora seja lgico pensar que quantos mais graus de liberdade tivermos mais flexvel a modelao, a verdade que um nmero excessivo
de parmetros pode conduzir a modelos pouco realistas. Esse fenmeno
evidente na Figura 25 onde mostramos uma perspectiva de um conjunto
de colunas cujos parmetros foram escolhidos aleatoriamente.
Na verdade, de acordo com os cnones da Ordem Drica, os diversos
parmetros que regulam a forma de uma coluna devem relacionar-se entre
si segundo um conjunto de propores bem definidas. Vitrvio40 , no seu
famoso tratado de arquitectura, considera que essas propores derivam
das propores do prprio ser humano:
40
Vitrvio foi um escritor, arquitecto e engenheiro romano que viveu no sculo um antes
de Cristo e autor do nico tratado de arquitectura que sobreviveu a antiguidade.
116
117
(xyz 0 0
(xyz 3 0
(xyz 6 0
(xyz 9 0
(xyz 12 0
(xyz 15 0
0)
0)
0)
0)
0)
0)
0.3
0.5
0.4
0.5
0.5
0.4
0.2)
0.3)
0.2)
0.4)
0.5)
0.7)
41
A Ordem Drica estabelece ainda mais uma relao entre os parmetros das colunas,
relao essa que s iremos implementar na seco 7.10.
118
7.8
Seleco
As propores de Vitrvio permitiram-nos reduzir o nmero de parmetros independentes de uma coluna Drica a apenas dois: o raio da base
do fuste e o raio da base do coxim. Contudo, no parece correcto que estes parmetros sejam totalmente independentes pois isso permite construir
colunas aberrantes em que o topo do fuste mais largo do que a base, tal
como acontece com a coluna mais direita na Figura 26.
Na verdade, a caracterizao da Ordem Drica que apresentmos encontrase incompleta pois, acerca das propores das colunas, Vitrvio afirmou
ainda que:
. . . se uma coluna tem quinze ps ou menos, divida-se a
largura na base em seis partes e usem-se cinco dessas partes
para formar a largura no topo, . . . [Vitrvio, Os Dez Livros da
Arquitectura, Livro III, Cap. 3.1]
At agora, fomos capazes de traduzir todas as regras que fomos anunciando mas, desta vez, a traduo levanta-nos uma nova dificuldade: ser
possvel traduzir uma afirmao da forma se, ento para Auto Lisp?
O termo se, ento permite-nos executar uma aco dependendo de
uma determinada condio ser verdadeira ou falsa: se uma coluna tem
quinze ps ou menos, ento o topo da coluna tem 56 da base, caso contrrio,
. . . . Na linguagem Lisp, estes termos descrevem uma forma de actuao
que se denomina de estrutura de controle de seleco. A seleco permitenos escolher uma via de aco mas apenas se uma determinada condio
for verdadeira.
A estrutura de controle de seleco mais sofisticada que a sequenciao. Ela baseia-se na utilizao de expresses condicionais para decidir
qual a prxima expresso a avaliar. A forma mais simples desta estrutura
de controle o if cuja sintaxe a seguinte:
(if condicional
consequente
alternativa)
Muitas outras funes podem ser definidas custa do if. Por exemplo,
para calcularmos o valor absoluto de um nmero x, |x|, temos de saber se
ele negativo. Se for, o seu valor absoluto o seu simtrico, caso contrrio
ele prprio. Eis a definio:
(defun abs (x)
(if (< x 0)
(- x)
x))
1 se x < 0
sgn x = 0
se x = 0
1
caso contrrio
120
Quando definimos esta funo em Lisp notamos que necessrio empregar mais do que um if:
(defun signum (x)
(if (< x 0)
-1
(if (= x 0)
0
1)))
7.9
O cond aceita qualquer nmero de argumentos. Cada argumento denominado clusula e constitudo por uma lista de expresses. A semntica
do cond consiste em avaliar sequencialmente a primeira expresso expri,0
de cada clusula at encontrar uma cujo valor seja verdade. Nesse momento, o cond avalia todas as restantes expresses dessa clusula e devolve
o valor da ltima. Se nenhuma das clusulas tiver uma primeira expresso
que avalie para verdade, o cond devolve nil. Se a clusula cuja primeira
expresso verdade no contiver mais expresses, o cond devolve o valor
dessa primeira expresso.
importante perceber que os parntesis que envolvem as clusulas no
correspondem a nenhuma combinao: eles simplesmente fazem parte da
sintaxe do cond e so necessrios para separar as clusulas umas das outras.
A pragmtica usual para a escrita de um cond (em especial quando
cada clusula contm apenas duas expresses) consiste em alinhar as expresses umas debaixo das outras.
Usando o cond, a funo sinal pode ser escrita de forma mais simples:
(defun signum (x)
(cond ((< x 0)
121
-1)
((= x 0)
0)
(t
1)))
A forma cond no estritamente necessria na linguagem pois possvel fazer exactamente o mesmo com uma combinao entre formas if
encadeadas e formas progn, tal como a seguinte equivalncia o demonstra:
(cond (expr0,0 expr0,1 ... expr0,n )
(expr1,0 expr1,1 ... expr1,m )
.
.
.
(exprk,0 exprk,1 ... exprk,p ))
m
(if expr0,0
(progn
expr0,1 ... expr0,n )
(if expr1,0
(progn
expr1,1 ... expr1,m )
..
.
(if exprk,0
(progn
exprk,1 ... exprk,p )
nil)))
Contudo, pragmaticamente falando, a forma cond pode simplificar substancialmente o programa quando o nmero de if encadeados maior que
um ou dois ou quando se pretende usar sequenciao no consequente ou
alternativa do if.
122
Exerccio 7.9.3 Defina uma funo soma-maiores que recebe trs nmeros como argumento e determina a soma dos dois maiores.
Exerccio 7.9.4 Defina a funo max3 que recebe trs nmeros como argumento e calcula o
maior entre eles.
Exerccio 7.9.5 Defina a funo segundo-maior que recebe trs nmeros como argumento
e devolve o segundo maior nmero, i.e., que est entre o maior e o menor.
7.10
O p foi a unidade fundamental de medida durante inmeros sculos mas a sua real
dimenso variou ao longo do tempo. O comprimento do p internacional de 304.8 milmetros e foi estabelecido por acordo em 1958. Antes disso, vrios outros comprimentos
foram usados, como o p Drico de 324 milmetros, os ps Jnico e Romano de 296 milmetros, o p Ateniense de 315 milmetros, os ps Egpcio e Fencio de 300 milmetros, etc.
123
O fragmento anterior corresponde, obviamente, afirmao: se uma coluna tem menos de quinze ps, divida-se a largura na base em seis partes e usem-se
cinco dessas partes para formar a largura no topo. No caso de a coluna no ter
menos de quinze ps, ento passamos ao caso seguinte: se a coluna tem entre
quinze e vinte ps, divida-se a largura na base em seis partes e meio e usem-se cinco
e meio dessas partes para a largura no topo da coluna. A traduo deste segundo
caso permite-nos escrever:
(defun raio-topo-fuste (raio-base altura)
(cond ((< altura 15)
(* (/ 5.0 6.0) raio-base))
((and (>= altura 15) (< altura 20))
(* (/ 5.5 6.5) raio-base))
...))
(raio-base altura)
(* (/ 5.0 6.0) raio-base))
(* (/ 5.5 6.5) raio-base))
(* (/ 6.0 7.0) raio-base))
(* (/ 6.5 7.5) raio-base))
(* (/ 7.0 8.0) raio-base))
124
1
2
1
2
50
7
8
40
6 12
7 12
30
6
7
20
15
5 12
6 12
5
6
6+136/2
7+136/2
= 74
75 = 0.987. Este valor, por ser muito prximo da unidade, mostra
que a coluna seria praticamente cilndrica.
Com base nestas consideraes, podemos agora definir uma funo
que, dado um nmero inteiro representando a altura da coluna em ps,
calcula a razo entre o topo e a base da coluna. Antes, contudo, convm
simplificar a frmula para as colunas com altura no inferior a 15 ps. Assim,
r=
6 + b a20
10 c
a20
7 + b 10 c
1
2
1
2
a
a
12 + b a20
12 + b 10
c2
c
10 + b 10
10 c
=
=
a
a
a20
14 + b 10 c 2
12 + b 10 c
14 + b 10 c
O seguinte exemplo de utilizao da funo produz a sequncia de colunas apresentadas na Figura 27:43
43
126
7.11
(defun xy (x y)
(list x y))
(defun cx (c)
(car c))
(defun cy (c)
(cadr c))
Vimos tambm, na seco 4.6 que possvel definir as coordenadas tridimensionais como uma generalizao bvia do tipo anterior. Para isso,
bastou-nos preservar as posies das coordenadas bi-dimensionais x e y na
representao de coordenadas tri-dimensionais, o que implica colocarmos
a coordenada z a seguir s outras duas. Isto levou-nos a definir o construtor
de coordenadas Cartesianas tri-dimensionais xyz com a seguinte forma:
(defun xyz (x y z)
(list x y z))
128
Usando estas funes agora mais simples definir correctamente o selector cz: para coordenadas bi-dimensionais, devolve zero. Para coordenadas tri-dimensionais, devolve o terceiro elemento da lista de coordenadas.
(defun cz (c)
(if (xy? c)
0
(caddr c)))
passa a ser directamente aplicvel a coordenadas bi-dimensionais sem qualquer tipo de alterao.
Infelizmente, nem todas as funes conseguem funcionar inalteradas.
Por exemplo, consideremos a funo +xy que permitia deslocar coordenadas bi-dimensionais:
(defun +xy (c x y)
(xy (+ (cx c) x)
(+ (cy c) y)))
Como bvio pela anlise da funo anterior, se ela for aplicada a uma
coordenada tri-dimensional, perde-se a coordenada z, o que manifestamente indesejvel. Para evitar este problema e, ao mesmo tempo, preservar
a compatibilidade com o caso bi-dimensional, temos de distinguir os dois
casos:
129
(defun +xy (c x y)
(if (xy? c)
(xy (+ (cx c) x)
(+ (cy c) y))
(xyz (+ (cx c) x)
(+ (cy c) y)
(cz c))))
(+xy (xy 1 2) 4 5)
7)
(+xy (xyz 1 2 3) 4 5)
7 3)
Uma vez que a funo +pol est definida em termos da funo +xy
e esta j sabe tratar coordenadas tri-dimensionais, tambm +pol saber
tratar coordenadas tri-dimensionais e, consequentemente, no precisa de
ser redefinida. O mesmo se pode dizer das funes +x e +y que apenas
dependem de +xy.
Finalmente, consideremos a definio da funo +c que apresentmos
na seco 4.11 e que se destinava a deslocar um ponto ao longo de um
vector (especificado pelas coordenadas da sua extremidade):
(defun +c (p0 p1)
(xy (+ (cx p0) (cx p1))
(+ (cy p0) (cy p1))))
Agora, temos:
_$
(4
_$
(4
_$
(3
_$
(3
(+c (xy 1 2)
6)
(+c (xy 1 2)
6 5)
(+c (xyz 0 1
5 2)
(+c (xyz 0 1
5 7)
(xy 3 4))
(xyz 3 4 5))
2) (xy 3 4))
2) (xyz 3 4 5))
Para alm da soma de um vector a um ponto por vezes til considerar a operao inversa, que subtrai um vector a um ponto, i.e., que
determina a origem do vector cujo destino o ponto dado ou, equivalentemente, as projeces do vector que liga os dois pontos dados. Por analogia
com a operao +c, vamos denominar esta operao de -c e a sua definio
ser, obviamente:
(defun -c (p0 p1)
(if (and (xy? p0) (xy? p1))
(xy (- (cx p0) (cx p1))
(- (cy p0) (cy p1)))
(xyz (- (cx p0) (cx p1))
(- (cy p0) (cy p1))
(- (cz p0) (cz p1)))))
Agora, temos:
_$
(1
_$
(3
_$
(3
_$
(3
_$
(4
(-c (xy 4 6)
2)
(-c (xy 4 6)
4))
(-c (xyz 4 6
4 0)
(-c (xyz 4 6
4 5)
(-c (xyz 5 7
5 6)
(xy 3 4))
(xy 1 2))
3) (xyz 1 2 3))
5) (xy 1 2))
9) (xyz 1 2 3))
131
Pode ser tambm til poder multiplicar uma coordenada por um factor, correspondendo a uma simples homotetia. Mais uma vez, temos de
distinguir os dois casos de pontos bi- e tri-dimensionais:
(defun *c (p f)
(if (xy? p)
(xy (* (cx p) f)
(* (cy p) f))
(xyz (* (cx p) f)
(* (cy p) f)
(* (cz p) f))))
c1)
c0) (cx c1))
c0) (cy c1))
c0) (cz c1))))
7.12
Coordenadas Cilndricas
Tal como podemos verificar na Figura 28, um ponto, em coordenadas cilndricas, caracteriza-se por um raio assente no plano z = 0, um ngulo
que esse raio faz com o eixo x e por uma cota z. fcil de ver que o raio e
132
z
y
x
Figura 28: Coordenadas cilndricas.
o ngulo correspondem s coordenadas polares da projeco do ponto no
plano z = 0.
Dado um ponto (, , z) em coordenadas cilndricas, o mesmo ponto
em coordenadas Cartesianas
( cos , sin , z)
De igual modo, dado um ponto (x, y, z) em coordenadas Cartesianas, o
mesmo ponto em coordenadas cilndricas
(
p
y
x2 + y 2 , atan , z)
x
Estas equivalncias permitem-nos definir uma funo que constri pontos em coordenadas cilndricas empregando as coordenadas Cartesianas
como representao cannica:
(defun cil (ro fi z)
(xyz (* ro (cos fi))
(* ro (sin fi))
z))
133
(defun +cil (p ro fi z)
(+c p (cil ro fi z)))
Exerccio 7.12.1 Defina os selectores cil-ro, cil-fi e cil-z que devolvem, respectivamente, os componentes , e z de um ponto construdo pelo construtor cil.
Existem inmeras curvas, superfcies e volumes que so mais simplesmente descritos usando coordenadas cilndricas do que usando coordenadas rectangulares. Por exemplo, a equao paramtrica de uma hlice, em
coordenadas cilndricas, trivial:
(, , z) = (1, t, t)
No entanto, em coordenadas rectangulares, somos obrigados a empregar
alguma trigonometria para obter a equao equivalente:
(x, y, z) = (cos t, sin t, t)
Exerccio 7.12.2 Defina uma funo escadas capaz de construir uma escada em hlice. A
imagem seguinte mostra trs exemplos destas escadas.
Como se pode ver pela imagem anterior, a escada constituda por um cilindro central
no qual se apoiam 10 degraus cilndricos. Para facilitar a experimentao considere que o
cilindro central de raio r. Os degraus so iguais ao cilindro central, possuem 10 raios de
comprimento e esto dispostos a alturas progressivamente crescentes. Cada degrau est
a uma altura h em relao ao degrau anterior e, visto em planta, faz um ngulo com o
degrau anterior.
A funo escada dever receber as coordenadas do centro da base do cilindro central,
o raio r, a altura h e o ngulo . A ttulo de exemplo, considere que as trs escadas anteriores
foram construdas pelas seguintes invocaes:
(escada (xyz 0 0 0) 1.0 3 (/ pi 6))
(escada (xyz 0 40 0) 1.5 5 (/ pi 9))
(escada (xyz 0 80 0) 0.5 6 (/ pi 8))
134
P
y
7.13
Coordenadas Esfricas
135
psi)
psi) (cos fi))
psi) (sin fi))
psi))))
7.14
Recurso
Vimos que as nossas funes, para fazerem algo til, precisam de invocar
outras funes. Por exemplo, se j tivermos a funo que calcula o quadrado de um nmero e pretendermos definir a funo que calcula o cubo
de um nmero, podemos facilmente faz-lo custa do quadrado e de uma
multiplicao adicional, i.e.:
(defun cubo (x)
(* (quadrado x) x))
Como bvio, podemos continuar a definir sucessivamente novas funes para calcular potncias crescentes mas isso no s moroso como ser
sempre limitado. Seria muito mais til podermos generalizar o processo
e definir simplesmente a funo potncia que, a partir de dois nmeros (a
base e o expoente) calcula o primeiro elevado ao segundo.
No entanto, aquilo que fizemos para a quarta-potencia, o cubo e
o quadrado do-nos uma pista muito importante: se tivermos uma funo
que calcula a potncia de expoente imediatamente inferior, ento basta-nos uma
multiplicao adicional para calcular a potncia seguinte.
Dito de outra forma, temos:
(defun potencia (x n)
(* (potencia-inferior x n) x))
Embora tenhamos conseguido simplificar o problema do clculo de potncia, sobrou uma questo por responder: como podemos calcular a potncia imediatamente inferior? A resposta poder no ser bvia mas, uma
136
A funo anterior um exemplo de uma funo recursiva, i.e., uma funo que est definida em termos de si prpria. Dito de outra forma, uma
funo recursiva uma funo que se usa a si prpria na sua definio. Esse
uso bvio quando desenrolamos a avaliao de (potencia 4 3):
(*
(* (*
(potencia 4 3)
(* (potencia 4 2) 4)
(* (potencia 4 1) 4) 4)
(* (potencia 4 0) 4) 4) 4)
(* (* (* 1 4) 4) 4)
(* (* 4 4) 4)
(* 16 4)
64
(
1,
se n = 0
n! =
n (n 1)!, caso contrrio.
A traduo desta frmula para Lisp directa:
(defun factorial (n)
(if (zerop n)
1
(* n (factorial (- n 1)))))
(* -1 (factorial -2))
(* -1 (* -2 (factorial -3)))
(* -1 (* -2 (* -3 (factorial -4))))
(* -1 (* -2 (* -3 (* -4 (factorial -5))))))
(* -1 (* -2 (* -3 (* -4 (* -5 (factorial -6))))))
...
O caso mais frequente de erro numa funo recursiva a recurso nunca
parar, ou porque no se detecta correctamente o caso bsico ou por a recurso no diminuir a complexidade do problema. Neste caso, o nmero
de invocaes recursivas cresce indefinidamente at esgotar a memria do
computador, altura em que o programa gera um erro. No caso do Auto
Lisp, esse erro no inteiramente bvio pois o avaliador apenas interrompe
a avaliao sem apresentar qualquer resultado. Eis um exemplo:
_$ (factorial 3)
6
_$ (factorial -1)
_$
muito importante compreendermos bem o conceito de recurso. Embora a princpio possa ser difcil abarcar por completo as implicaes deste
conceito, a recurso permite resolver, com enorme simplicidade, problemas
aparentemente muito complexos.
Como iremos ver, tambm em arquitectura a recurso um conceito
fundamental.
140
Exerccio 7.14.1 A funo de Ackermann definida para nmeros no negativos da seguinte forma:
8
>
se m = 0
<n + 1
A(m, n) = A(m 1, 1)
se m > 0 e n = 0
>
:
A(m 1, A(m, n 1)) se m > 0 e n > 0
Defina, em Lisp, a funo de Ackermann.
Exerccio 7.14.2 Indique o valor de
1. (ackermann 0 8)
2. (ackermann 1 8)
3. (ackermann 2 8)
4. (ackermann 3 8)
5. (ackermann 4 8)
Exerccio 7.14.3 Defina uma funo denominada escada que, dado um ponto P , um nmero de degraus, o comprimento do espelho e e o comprimento do cobertor c de cada
degrau, desenha a escada em AutoCad com o primeiro espelho a comear a partir do ponto
dado, tal como se v na imagem seguinte:
e
c
P
Exerccio 7.14.4 Defina uma funo equilibrio-circulos capaz de criar qualquer uma
das figuras apresentadas em seguida:
141
Note que os crculos possuem raios que esto em progresso geomtrica de razo f ,
com 0 < f < 1. Assim, cada crculo (excepto o primeiro) tem um raio que o produto de f
pelo raio do crculo maior em que est apoiado. O crculo mais pequeno de todos tem raio
maior ou igual a 1. A sua funo dever ter como parmetros o centro e o raio do crculo
maior e ainda o factor de reduo f .
Exerccio 7.14.5 Considere o desenho de crculos em torno de um centro, tal como apresentado na seguinte imagem:
y
r1
r0
Escreva uma funo denominada circulos-concentricos que, a partir das coordenadas p do centro de rotao, do nmero de crculos n, do raio de translaco r0 , do raio
de circunferncia r1 , do ngulo inicial e do incremento de ngulo , desenha os crculos
tal como apresentados na figura anterior.
Teste a sua funo com os seguintes expresses:
(circulos-concentricos (xy 0 0) 10 10 2 0 (/ pi 5))
(circulos-concentricos (xy 25 0) 20 10 2 0 (/ pi 10))
(circulos-concentricos (xy 50 0) 40 10 2 0 (/ pi 20))
Exerccio 7.14.6 Considere o desenho de flores simblicas compostas por um crculo interior em torno da qual esto dispostos crculos concntricos correspondentes a ptalas. Estes
crculos devero ser tangentes uns aos outros e ao crculo interior, tal como se apresenta na
seguinte imagem:
142
Defina a funo flor que recebe apenas o ponto correspondente ao centro da flor, o
raio do crculo interior e o nmero de ptalas.
Teste a sua funo com as expresses
(flor (xy 0 0) 5 10)
(flor (xy 18 0) 2 10)
(flor (xy 40 0) 10 20)
7.15
(defun potencia
(if (= n 0)
1
(* (potencia x (- n 1)) x)))
Este ltimo erro, como bvio, no tem a ver com a regras da gramtica
do Lisp: a frase da invocao da funo factorial est correcta. O
problema est no facto de no fazer sentido calcular o factorial de uma
string pois o clculo do factorial envolve operaes aritmticas e estas no
so aplicveis a strings. Assim sendo, o erro tem a ver com o significado
da frase escrita, i.e., com a semntica. Trata-se, portanto, de um erro
semntico.
A recurso infinita outro exemplo de um erro semntico. Vimos que a
funo factorial s pode ser invocada com um argumento no negativo ou
provoca recurso infinita. Consequentemente, se usarmos um argumento
negativo estaremos a cometer um erro semntico.
7.15.1
Trace
H casos de erros semnticos que podem ser detectados antes da execuo do programa
mas essa deteco depende muito da qualidade da implementao da linguagem e da sua
capacidade em antecipar as consequncias dos programas.
144
nome das funes cuja invocao se pretende analisar e altera essas funes
de forma a que elas escrevam as sucessivas invocaes com os respectivos
argumentos, bem como o resultado da invocao. Se o ambiente do Visual
Lisp estiver activo, a escrita feita numa janela especial do ambiente do
Visual Lisp denominada Trace,46 caso contrrio, feita na janela de comandos do AutoCad. A informao apresentada em resultado do trace ,
em geral, extremamente til para a depurao das funes.
Por exemplo, para visualizarmos uma invocao da funo factorial,
consideremos a seguinte interaco:
_$ (trace factorial)
FACTORIAL
_$ (factorial 5)
120
Note-se, no texto anterior escrito em consequncia do trace, que a invocao que fizemos da funo factorial aparece encostada esquerda.
Cada invocao recursiva aparece ligeiramente para a direita, permitindo
assim visualizar a profundidade da recurso, i.e., o nmero de invocaes recursivas. O resultado devolvido por cada invocao aparece alinhado na mesma coluna dessa invocao.
de salientar que a janela de Trace no tem dimenso infinita, pelo
que as recurses excessivamente profundas acabaro por no caber na janela. Neste caso, o Visual Lisp reposiciona a escrita na coluna esquerda
mas indica numericamente o nvel de profundidade em que se encontra.
Por exemplo, para o (factorial 15), aparece:
46
145
No caso de recurses infinitas, apenas so mostradas as ltimas invocaes realizadas antes de ser gerado o erro. Por exemplo, para (factorial -1),
teremos:
...
[19215]
Entering (FACTORIAL -19216)
[19216]
Entering (FACTORIAL -19217)
[19217]
Entering (FACTORIAL -19218)
[19218]
Entering (FACTORIAL -19219)
[19219]
Entering (FACTORIAL -19220)
[19220] Entering (FACTORIAL -19221)
[19221]
Entering (FACTORIAL -19222)
[19222]
Entering (FACTORIAL -19223)
[19223]
Entering (FACTORIAL -19224)
[19224]
Entering (FACTORIAL -19225)
146
...
[19963]
Entering (FACTORIAL -19964)
[19964]
Entering (FACTORIAL -19965)
[19965]
Entering (FACTORIAL -19966)
[19966]
Entering (FACTORIAL -19967)
[19967]
Entering (FACTORIAL -19968)
[19968]
Entering (FACTORIAL -19969)
[19969]
Entering (FACTORIAL -19970)
[19970] Entering (FACTORIAL -19971)
[19971]
Entering (FACTORIAL -19972)
[19972]
Entering (FACTORIAL -19973)
[19973]
Entering (FACTORIAL -19974)
[19974]
Entering (FACTORIAL -19975)
[19975]
Entering (FACTORIAL -19976)
Note que os crculos possuem raios que esto em progresso geomtrica de razo 12 .
Dito de outra forma, os crculos mais pequenos tm metade do raio do crculo maior que
lhes adjacente. Os crculos mais pequenos de todos tm raio maior ou igual a 1. A sua
funo dever ter como parmetros apenas o centro e o raio do crculo maior.
Exerccio 7.15.3 Defina uma funo denominada serra que, dado um ponto P , um nmero de dentes, o comprimento c de cada dente e a altura a de cada dente, desenha uma
serra em AutoCad com o primeiro dente a comear a partir do ponto P , tal como se v na
imagem seguinte:
147
a
P
c
Exerccio 7.15.4 Defina uma funo losangulos capaz de criar a figura apresentada em
seguida:
7.16
Templos Dricos
148
Na prtica, nem sempre as regras propostas por Vitrvio representavam a realidade dos templos e, frequentemente, a distancia intercolunar
varia, sendo mais reduzida nas extremidades para dar um aspecto mais
robusto ao templo.
Para simplificar a nossa implementao, vamos ignorar estes detalhes
e, ao invs de distinguir vrios stilo, vamos simplesmente usar como parmetros as coordenadas da base do eixo da primeira coluna, a altura da
coluna, a separao entre os eixos das colunas47 (em termos de um vector de deslocao entre colunas) e, finalmente, o nmero de colunas que
pretendemos colocar. O vector de deslocao entre colunas destina-se a
permitir orientar as colunas em qualquer direco e no s ao longo do eixo
dos x ou y.
O raciocnio para a definio desta funo , mais uma vez, recursivo:
Se o nmero de colunas a colocar for zero, ento no preciso fazer
nada e podemos simplesmente retornar nil.
Caso contrrio, colocamos uma coluna na coordenada indicada e, recursivamente, colocamos as restantes colunas a partir da coordenada
que resulta de aplicarmos o vector de deslocao coordenada actual. Como so duas aces que queremos realizar sequencialmente,
teremos de usar o operador progn para as agrupar numa aco conjunta.
Traduzindo este raciocnio para Lisp, temos:
(defun colunas-doricas (p altura separacao colunas)
(if (= colunas 0)
nil
(progn
(coluna-dorica p altura)
(colunas-doricas (+c p separacao)
altura
separacao
(- colunas 1)))))
149
150
A partir do momento em que sabemos construir uma fileira de colunas torna-se relativamente fcil a construo das quatro fileiras necessrias
para os templos em peristilo. Normalmente, a descrio destes templos
faz-se em termos do nmero de colunas da fronte e do nmero de colunas
do lado, mas assumindo que as colunas dos cantos contam para ambas as
medidas. Isto quer dizer que num templo de, por exemplo, 6 12 colunas
existem, na realidade, apenas 4 2 + 10 2 + 4 = 32 colunas. Para a construo do peristilo, para alm do nmero de colunas das frontes e lados,
ser necessrio conhecer a distncia entre colunas nas frontes e nos lados e,
claro, a altura das colunas.
Em termos de algoritmo, vamos comear por construir as frontes, desenhando todas as colunas incluindo os cantos. Em seguida construmos os
lados, tendo em conta que os cantos j foram colocados. Para simplificar,
vamos considerar que o templo tem as frontes paralelas ao eixo x (e os lados paralelos ao eixo y) e que a primeira coluna colocada num ponto P
dado como primeiro parmetro. Assim, temos:
(defun peristilo-dorico (p
n-fronte n-lado
d-fronte d-lado
altura)
(colunas-doricas p
altura (xy d-fronte 0) n-fronte)
(colunas-doricas (+xy p 0 (* (1- n-lado) d-lado))
altura (xy d-fronte 0) n-fronte)
(colunas-doricas (+xy p 0 d-lado)
altura (xy 0 d-lado) (- n-lado 2))
(colunas-doricas (+xy p (* (1- n-fronte) d-fronte) d-lado)
altura (xy 0 d-lado) (- n-lado 2)))
152
rp
ab
rb
x
rb
Figura 33: Corte da base de um Tholos. A base composta por uma sequncia de cilindros sobrepostos cujo raio de base rb encolhe de rb a cada degrau e cuja altura incrementa ab a cada degrau.
154
Para o posicionamento das colunas, vamos tambm considerar um processo em que em cada passo apenas posicionamos uma coluna numa dada
posio e, recursivamente, colocamos as restantes colunas a partir da posio circular seguinte.
Dada a sua estrutura circular, a construo deste gnero de edifcios
simplificada pelo uso de coordenadas circulares. De facto, podemos conceber um processo recursivo que, a partir do raio rp do peristilo e do ngulo
inicial , coloca uma coluna nessa posio e que, de seguida, coloca as restantes colunas usando o mesmo raio mas incrementando o ngulo de
, tal como se apresenta na Figura 34. O incremento angular obtmse pela diviso da circunferncia pelo nmero n de colunas a colocar, i.e.,
= 2
n . Uma vez que as colunas se dispem em torno de um crculo,
o clculo das coordenadas de cada coluna fica facilitado pelo uso de coordenadas polares. Tendo este algoritmo em mente, a definio da funo
fica:
(defun colunas-tholos (p n-colunas raio fi d-fi altura)
(if (= n-colunas 0)
nil
(progn
(coluna-dorica (+pol p raio fi) altura)
(colunas-tholos p
(1- n-colunas)
raio
(+ fi d-fi)
d-fi
altura))))
Finalmente, definimos a funo tholos que, dados os parmetros necessrios s duas anteriores, as invoca em sequncia:
155
ap
ab
rb
rp
y
rp
x
Figura 34: Esquema da construo de um Tholos: rb o raio da base, rp a
distncia do centro das colunas ao centro da base, ap a altura das coluna,
ab a altura da base, o ngulo inicial de posicionamento das colunas e
o ngulo entre colunas.
156
Exerccio 7.16.1 Uma observao atenta do Tholos apresentado na Figura 35 mostra que
existe um erro: os bacos das vrias colunas so paralelos uns aos outros (e aos eixos das
abcissas e ordenadas) quando, na realidade, deveriam ter uma orientao radial. Essa diferena evidente quando se compara uma vista de topo do desenho actual ( esquerda) com
a mesma vista daquele que seria o desenho correcto ( direita):
157
Defina uma nova funo coluna-dorica-rodada que, para alm da altura da coluna, recebe ainda o ngulo de rotao que a coluna deve ter. Uma vez que o fuste e o
coxim da coluna tm simetria axial, esse ngulo de rotao s influencia o baco, pelo que
dever tambm definir uma funo para desenhar um baco rodado.
De seguida, redefina a funo colunas-tholos de modo a que cada coluna esteja
orientada correctamente relativamente ao centro do Tholos.
Exerccio 7.16.2 Considere a construo de uma torre composta por vrios mdulos em
que cada mdulo tem exactamente as mesmas caractersticas de um Tholos, tal como se
apresenta na figura abaixo, esquerda:
O topo da torre tem uma forma semelhante da base de um Tholos, embora com mais
degraus.
158
Exerccio 7.16.5 Considere a criao de uma cidade no espao, composta apenas por cilindros com dimenses progressivamente mais pequenas, unidos uns aos outros por intermdio de esferas, tal como se apresenta (em perspectiva) na imagem seguinte:
159
Defina uma funo que, a partir do centro da cidade e do raio dos cilindros centrais
constri uma cidade semelhante representada.
7.17
A Ordem Jnica
161
P1 ~v0
rf
P
~v1 ~v
rf f f
2
P2
P3
rf f
162
Como se v pela figura, para se desenhar a espiral temos de ir desenhando sucessivos quartos de circunferncia. O primeiro quarto de circunferncia ser centrado no ponto P e ter raio r. Este primeiro arco vai desde
o ngulo /2 at ao ngulo . O segundo quarto de circunferncia ser centrado no ponto P1 e ter raio r f , sendo f um coeficiente de reduo da
espiral. Este segundo arco vai desde o ngulo at ao ngulo 23 . Um detalhe importante a relao entre as coordenadas P1 e P : para que o segundo
arco tenha uma extremidade coincidente com o primeiro arco, o seu centro
tem de estar na extremidade do vector ~v0 de origem em P , comprimento
r(1 f ) e ngulo igual ao ngulo final do primeiro arco.
Este processo dever ser seguido para todos os restantes arcos de circunferncia, i.e., teremos de calcular as coordenadas P2 , P3 , etc., bem como
os raios r f f , r f f f , etc, necessrios para traar os sucessivos arcos
de circunferncia.
Dito desta forma, o processo de desenho parece ser complicado. No
entanto, possivel reformul-lo de modo a ficar muito mais simples. De
facto, podemos pensar no desenho da espiral completa como sendo o desenho de um quarto de circunferncia seguido do desenho de uma espiral
mais pequena. Mais concretamente, podemos especificar o desenho da espiral de centro no ponto P , raio r e ngulo inicial como sendo o desenho
de um arco de circunferncia de raio r centrado em P com ngulo inicial
e final + 2 seguido de uma espiral de centro em P + ~v , raio r f e ngulo
inicial + 2 . O vector ~v ter origem em P , mdulo r(1 f ) e ngulo + 2 .
Obviamente, sendo este um processo recursivo, necessrio definir o
caso de paragem, havendo (pelo menos) duas possibilidades:
Terminar quando o raio r inferior a um determinado limite.
Terminar quando o ngulo superior a um determinado limite.
Por agora, vamos considerar a segunda possibilidade. De acordo com o
nosso raciocnio, vamos definir a funo que desenha a espiral de modo a
receber, como parmetros, o ponto inicial p, o raio inicial r, o ngulo inicial
a-ini, o ngulo final a-fin e o factor de reduo f:
(defun espiral (p r a-ini a-fin f)
(if (> a-ini a-fin)
nil
(progn
(quarto-circunferencia p r a-ini)
(espiral (+pol p (* r (- 1 f)) (+ a-ini (/ pi 2)))
(* r f)
163
(+ a-ini (/ pi 2))
a-fin
f))))
r a-ini)
p r a-ini) "_a" 90)
a-ini) "")
(+ a-ini (/ pi 2))) ""))
164
Figura 39: Vrias espirais com razes de reduo de 0.9, 0.7 e 0.5, respectivamente.
(espiral (xy 0 0) 10 (/ pi 2) (/ pi 2) (* pi 6) 0.8)
claro que agora podemos facilmente construir outras espirais. As seguintes expresses produzem as espirais representadas na Figura 39:
(espiral (xy 0 0) 10 (/ pi 2) (/ pi 2) (* pi 6) 0.9)
(espiral (xy 20 0) 10 (/ pi 2) (/ pi 2) (* pi 6) 0.7)
(espiral (xy 40 0) 10 (/ pi 2) (/ pi 2) (* pi 6) 0.5)
Outra possibilidade de variao est no ngulo de incremento. As seguintes expresses experimentam aproximaes aos processos de Sebastiano Serlio (semi-circunferncias), Giuseppe Salviati (quartos-de-circunferncia)
e Guillaume Philandrier (oitavos-de-circunferncia):48
(espiral (xy 0 0) 10 (/ pi 2) pi (* pi 6) 0.8)
(espiral (xy 20 0) 10 (/ pi 2) (/ pi 2) (* pi 6) 0.8)
(espiral (xy 40 0) 10 (/ pi 2) (/ pi 4) (* pi 6) 0.8)
Note-se que se trata, to somente, de aproximaes. Os processos originais eram bastante mais complexos.
166
167
r1
r2
r2
r0
7.18
Recurso na Natureza
169
f c
f c
c
(x0 , y0 )
Figura 42: Parmetros de desenho de uma rvore.
tarmos esta teoria, vamos comear por considerar uma verso muito simplista de uma rvore, em que temos um tronco que, a partir de uma certa
altura, se divide em dois. Cada um destes subtroncos cresce fazendo um
certo ngulo com o tronco de onde emanou e com um comprimento que
dever ser uma fraco do comprimento desse tronco, tal como se apresenta na Figura 42. O caso de paragem ocorre quando o comprimento do
tronco se tornou to pequeno que, em vez de se continuar a diviso, aparece simplesmente uma outra estrutura. Para simplificar, vamos designar a
extremidade de um ramo por folha e iremos represent-la com um pequeno
crculo.
Para darmos dimenses rvore, vamos considerar que a funo arvore
recebe, como argumento, as coordenadas da base da rvore, o comprimento
do tronco e o ngulo actual do tronco. Para a fase recursiva, teremos como
parmetros o ngulo de abertura alpha que o novo tronco dever fazer
com o actual e o factor de reduo f do comprimento do tronco. O primeiro passo a computao do topo do tronco usando a funo +pol. Em
seguida, desenhamos o tronco desde a base at ao topo. Finalmente, testamos se o tronco desenhado suficientemente pequeno. Se for, terminamos
com o desenho de um crculo centrado no topo. Caso contrrio fazemos
uma dupla recurso para desenhar uma sub-rvore para a direita e outra
para a esquerda. A definio da funo fica:
(defun arvore (base comprimento angulo alfa f / topo)
(setq topo (+pol base comprimento angulo))
(ramo base topo)
(if (< comprimento 2)
(folha topo)
(progn
170
(arvore topo
(* comprimento f)
(+ angulo alfa)
alfa f)
(arvore topo
(* comprimento f)
(- angulo alfa)
alfa f))))
(defun ramo (base topo)
(command "_.line" base topo ""))
(defun folha (topo)
(command "_.circle" topo 0.2))
171
172
fe c
fd c
c
(x0 , y0 )
Figura 45: Parmetros de desenho de uma rvore com crescimento assimtrico.
(+ angulo alfa-e)
alfa-e f-e alfa-d f-d)
(arvore topo
(* comprimento f-d)
(- angulo alfa-d)
alfa-e f-e alfa-d f-d))))
A Figura 46 apresenta novos exemplos de rvores com diferentes ngulos de abertura e factores de reduo dos ramos esquerdo e direito, geradas
pelas seguintes expresses:
(arvore (xy 0 0) 20 (/ pi 2) (/ pi 8) 0.6 (/ pi 8) 0.7)
(arvore (xy 100 0) 20 (/ pi 2) (/ pi 4) 0.7 (/ pi 16) 0.7)
(arvore (xy 200 0) 20 (/ pi 2) (/ pi 6) 0.6 (/ pi 16) 0.8)
173
174
Funo
+
Argumentos
Vrios nmeros
Vrios nmeros
Vrios nmeros
Vrios nmeros
1+
1abs
sin
cos
atan
Um nmero
Um nmero
Um nmero
Um nmero
Um nmero
Um ou dois nmeros
sqrt
Um nmero no
negativo
Um nmero
Dois nmeros
exp
expt
Um nmero positivo
Vrios nmeros
Vrios nmeros
Dois ou mais
nmeros
log
max
min
rem
fix
float
gcd
Um nmero
Um nmero
Dois nmeros
Resultado
A adio de todos os argumentos. Sem argumentos, zero.
Com apenas um argumento, o seu simtrico. Com mais de um argumento, a subtraco ao primeiro de todos os restantes.
Sem argumentos, zero.
A multiplicao de todos os argumentos.
Sem argumentos, zero.
A diviso do primeiro argumento por todos os restantes. Sem argumentos, zero.
A soma do argumento com um.
A substraco do argumento com um.
O valor absoluto do argumento.
O seno do argumento (em radianos).
O cosseno do argumento (em radianos).
Com um argumento, o arco tangente do argumento (em radianos). Com dois argumentos, o arco tangente da diviso do primeiro pelo segundo (em radianos). O sinal
dos argumentos usado para determinar o
quadrante.
A raiz quadrada do argumento.
A exponencial de base e.
O primeiro argumento elevado ao segundo
argumento.
O logaritmo natural do argumento.
O maior dos argumentos.
O menor dos argumentos.
Com dois argumentos, o resto da diviso
do primeiro pelo segundo. Com mais argumentos, o resto da diviso do resultado
anterior pelo argumento seguinte.
O argumento sem a parte fraccionria.
O argumento convertido em nmero real.
O maior divisor comum dos dois argumentos.
Auto Lisp
(+ x0 x1 ...
(+ x)
(+)
(- x0 x1 ...
(- x)
(-)
(* x0 x1 ...
(* x)
(*)
(/ x0 x1 ...
(/ x)
(/)
(1+ x)
(1- x)
(abs x)
(sin x)
(cos x)
(atan x)
(atan x y)
(sqrt x)
(exp x)
(expt x y)
(log x)
(fix x)
xn )
xn )
xn )
xn )
Matemtica
x0 + x1 + . . . + xn
x
0
x0 x1 . . . xn
x
0
x0 x1 . . . xn
x
0
x0 /x1 / . . . /xn
x
0
x+1
x1
|x|
sin x
cos x
atan x
atan xy
x
x
e
xy
log x
bxc
176
Funo
strcat
Argumentos
Vrias strings
strlen
Vrias strings
substr
Uma
string,
um inteiro (o
ndice) e, opcionalmente,
outro
inteiro
(o nmero de
caracteres)
Uma string e
um
boleano
opcional
strcase
atof
Uma string
atoi
Uma string
itoa
rtos
Um nmero
Um, dois ou trs
nmeros
Resultado
A concatenao de todos os argumentos.
Sem argumentos, a string vazia .
O nmero de caracteres da concatenao
das strings. Sem argumentos, devolve
zero.
A parte da string que comea no ndice
dado e que tem o nmero de caracteres
dado ou todos os restantes caracteres no
caso de esse nmero no ter sido dado.
177