cap1 Introdução à linguagem Scheme -...

33
> cap1 Introdução à linguagem Scheme > sec1-1 Números > sec1-2 Expressões > sec1-3 Identificadores > sec1-4 Procedimentos Compostos > sec1-5 Varáveis locais > sec1-6 Estruturas de Selecção > sec1-7 Exercícios e Exemplos > sec1-8 Resumo A linguagem Scheme, apesar de poderosa, caracteriza-se por ter uma sintaxe simples, com poucas regras, que não exige nem muito tempo de aprendizagem (do aluno) nem muito espaço (de manuais), o que já não se poderá afirmar da generalidade das linguagens de programação. Assim, o esforço e atenção do professor e alunos incidirão, sobretudo, na programação e não tanto na ferramenta a utilizar na programação. Neste capítulo, faz-se uma breve introdução à linguagem Scheme, colocando desde logo ao nosso alcance a escrita de procedimentos e programas simples. Depois deste capítulo, a sintaxe do Scheme resumir-se-á, fundamentalmente, a notas pontuais ao longo de outros capítulos e a referências a um dos anexo (Anexo A). > sec1-1 Números Os Números são dados simples disponibilizados pela linguagem Scheme, que representam o próprio valor que devolvem. Por exemplo, o número 10, quando integrado numa expressão, devolve o valor 10, como seria de esperar. O número 35E2 é a representação exponencial do valor 3500, pois equivale a 35 x 10 2 (o expoente 2 é o número à direita de E), enquanto que o número 35E-3 representa o valor 0.035, por ser equivalente a 35 x 10 -3 . A partir deste momento, mas de uma forma muitíssimo limitada, já seria possível dialogar com o computador, através da linguagem Scheme. Para isso, torna-se necessário pôr em funcionamento um programa que entenda a sintaxe desta linguagem, e que poderá ser um interpretador 1 de Scheme. O interpretador coloca-se disponível para responder ao utilizador, pois apresenta-se num ciclo permanente de 1 Optou-se, em todos os exemplos apresentados, pela utilização do interpretador DrScheme, por se tratar de uma excelente ferramenta de origem universitária, disponível para várias plataformas, e distribuída gratuitamente em: http://www.cs.rice.edu/CS/PLT/packages/drscheme/download.html

Transcript of cap1 Introdução à linguagem Scheme -...

Page 1: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

> cap1 Introdução à linguagem Scheme

> sec1-1 Números > sec1-2 Expressões > sec1-3 Identificadores > sec1-4 Procedimentos Compostos > sec1-5 Varáveis locais > sec1-6 Estruturas de Selecção > sec1-7 Exercícios e Exemplos > sec1-8 Resumo A linguagem Scheme, apesar de poderosa, caracteriza-se por ter uma sintaxe simples, com poucas regras, que não exige nem muito tempo de aprendizagem (do aluno) nem muito espaço (de manuais), o que já não se poderá afirmar da generalidade das linguagens de programação. Assim, o esforço e atenção do professor e alunos incidirão, sobretudo, na programação e não tanto na ferramenta a utilizar na programação. Neste capítulo, faz-se uma breve introdução à linguagem Scheme, colocando desde logo ao nosso alcance a escrita de procedimentos e programas simples. Depois deste capítulo, a sintaxe do Scheme resumir-se-á, fundamentalmente, a notas pontuais ao longo de outros capítulos e a referências a um dos anexo (Anexo A).

> sec1-1 Números

Os Números são dados simples disponibilizados pela linguagem Scheme, que representam o próprio valor que devolvem. Por exemplo, o número 10, quando integrado numa expressão, devolve o valor 10, como seria de esperar. O número 35E2 é a representação exponencial do valor 3500, pois equivale a 35 x 102 (o expoente 2 é o número à direita de E), enquanto que o número 35E-3 representa o valor 0.035, por ser equivalente a 35 x 10-3. A partir deste momento, mas de uma forma muitíssimo limitada, já seria possível dialogar com o computador, através da linguagem Scheme. Para isso, torna-se necessário pôr em funcionamento um programa que entenda a sintaxe desta linguagem, e que poderá ser um interpretador1 de Scheme. O interpretador coloca-se disponível para responder ao utilizador, pois apresenta-se num ciclo permanente de 1 Optou-se, em todos os exemplos apresentados, pela utilização do interpretador DrScheme, por se tratar de uma excelente ferramenta de origem universitária, disponível para várias plataformas, e distribuída gratuitamente em: http://www.cs.rice.edu/CS/PLT/packages/drscheme/download.html

Page 2: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 2

leitura-cálculo-escrita, que se identifica através da visualização no ecrã de algum caracter especial2, como se indica de seguida.

> Este caracter significa que o Scheme está preparado para ler uma expressão, fornecida pelo utilizador.

> 10 A expressão, neste caso o número 10, após a actuação da tecla return, é calculada e o respectivo valor é visualizado no ecrã.

> 10 10

Vejamos outros exemplos. > 10 +10 > 35E2 3500.0 > 35E-2 0.35

> sec1-2 Expressões

Os exemplos apresentados referiam-se apenas a Expressões Simples, mas a maioria das situações que iremos encontrar exigem Expressões Compostas. A linguagem Scheme disponibiliza vários Procedimentos Primitivos, assim designados por fazerem parte da definição da própria linguagem, entre os quais se salientam os operadores aritméticos:

+ adição - subtracção * multiplicação / divisão

Nesta linguagem, as expressões utilizam uma notação pré-fixa, em que o operador aparece antes dos operandos. No primeiro exemplo que se segue, o operador aritmético da adição surge em primeiro lugar, seguido dos operandos 10 e 25.

> (+ 10 25) 35 > 10 25 37) (+72 > 10 15) (--5 > (- 10 15 5) -10

Estes exemplos são Expressões Compostas. Apresentam-se rodeadas por parêntesis e, dentro destes, aparece em primeiro lugar o operador, seguido dos vários operandos. 2 Sem recorrer à tradução, este caracter é designado por prompt, e vai ser representado por >. No diálogo entre o utilizador e o interpretador, a parte que cabe a este último será representada a cheio (bold), enquanto que a parte do utilizador surgirá em texto normal.

Page 3: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 3

A regra de cálculo de uma expressão composta segue os passos seguintes: ⇒ Em primeiro lugar, calcular cada um dos operandos da expressão; ⇒ Seguidamente, aplicar o operador aos operandos calculados.

> (* 2 6 30) 360

Do cálculo dos operandos 2, 6, e 30, resultam, respectivamente, os valores 2, 6 e 30. Aplicando-lhes o operador *, o valor resultante será 360.

> + 12 (- 45 38)) (19

Esta expressão apresenta dois operandos que serão previamente calculados, antes de se aplicar o operador +. O primeiro operando devolve imediatamente 12, pois é um número. Mas o segundo, (- 45 48), requer um pouco mais de trabalho. Este operando é, ele próprio, uma expressão composta exigindo, por seu turno, a aplicação da regra de cálculo de uma expressão composta: o cálculo dos seus operandos, 45 e 38, seguido da aplicação do operador, o procedimento primitivo -, de onde resulta o valor 7. Finalmente, estando calculados os operandos da expressão inicial, 12 e 7, será aplicado o operador, o procedimento primitivo +, resultando 19.

> (Exercício 1.1) Indicar como responderá o Scheme às expressões:

> (* (+ 34 30) 6) ? > (+ 23 (* 3 5 3) (- 22 2 34)) ? > (* (* 34 (- 4 5)) (+ 12 (/ 15 3))) ?

Quando uma expressão se torna de leitura complicada, o melhor será representá-la de uma forma mais adequada, alinhando verticalmente os operandos de cada um dos operadores da expressão3. A última expressão do Exercício 1.1 poderá então apresentar uma forma muito mais legível.

(* (* 34 (- 4 5)) (+ 12 (/ 15 3)))

O desenvolvimento desta expressão é indicado de seguida. (* (* (* (* 34 (* 34 -34 (- 4 -1) 5)) -578 (+ 12 (+ 12 17) (/ 15 5)) 3)))

3 Este tipo de formatação é normalmente disponibilizado quando se trabalha com o Scheme no computador.

Page 4: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 4

> sec1-3 Identificadores

É necessário, muitas vezes, definir novos entidades dando-lhes nomes. Assim é, por exemplo, quando se pretende definir novos procedimentos para além dos procedimentos primitivos ou, simplesmente, criar um identificador.

> (define lado-da-casa 16) lado-da-casa

O identificador lado-da-casa acabou de ser definido, tendo-se-lhe associado o valor 16. Isto poderá ser verificado ao pedir o cálculo do seu valor.

> lado-da-casa 16

Acabámos de utilizar define, uma das formas especiais do Scheme, que se representa agora na forma genérica.

(define identificador expressão)

Cada forma especial, como o próprio nome indica, tem no Scheme uma regra de cálculo especial. No caso de define, a regra é a seguinte:

⇒ Começar por calcular expressão; ⇒ Depois associar o valor de expressão ao identificador.

Quando se associa um dado numérico a um nome, é porque se deseja trabalhar com nomes e não directamente com números, o que significa trabalhar a um nível um pouco mais elevado. Por exemplo, o número 16 poderá significar muita coisa e, por isso mesmo, pouco nos dirá quando aparece numa expressão. Mas, pelo contrário, se em vez de 16 surge o nome lado-da-casa, inserido num certo contexto, poder-se-á imaginar do que se trata. Isto é um exemplo simples de uma Abstracção de Dados, conceito que, pela sua enorme importância em programação, será retomado noutro capítulo. O identificador lado-da-casa ficou ligado ou associado ao valor 16 e poderá ser incorporado em expressões.

> (+ lado-da-casa 3) 19 > 3 lado-da-casa -1) (*-48

Quanto aos identificadores, a regra de cálculo é:

⇒ Se um identificador está ligado a um valor, é devolvido esse valor; ⇒ Caso contrário, é assinalada uma mensagem de erro.

> (* 3 lado-da-moradia) reference to undefined identifier: lado-da-moradia

De facto, ao identificador lado-da-moradia não tinha sido previamente associado um valor, situação que foi oportunamente identificada e assinalada pelo Scheme, com uma mensagem apropriada.

Page 5: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 5

> sec1-4 Procedimentos Compostos

Para além dos procedimentos primitivos, é possível criar novos procedimentos, designados por procedimentos compostos. Em vez de ligar um número a um identificador, como se fez em lado-da-casa, vamos agora associar-lhe uma tarefa específica. Assim, quando o programador pretender executar essa tarefa, não terá mais do que chamá-la através do identificador respectivo, ou seja, através do seu nome. Em relação a este assunto, devemos distinguir muito bem duas fases: A definição do procedimento e a chamada do procedimento. Antes das formas genéricas utilizadas na definição e na chamada de procedimentos compostos, optou-se pela apresentação de um exemplo que deverá ser analisado com muita atenção. O procedimento quadrado, que se indica de seguida, é muito simples: Toma um valor numérico qualquer e devolve o quadrado desse valor.

(define quadrado ; nesta linha, é definido o nome do procedimento (lambda (x) ; x é o único parâmetro do procedimento (* x x))) ; aqui é definida a tarefa associada ao procedimento

Na definição de novos procedimentos recorremos ao procedimento primitivo lambda que não devolve um valor numérico, como acontecia com os operadores aritméticos, mas devolve, isso sim, um procedimento que realiza uma tarefa bem definida. Foi assim que o identificador quadrado, através de lambda, passou a estar associado a uma tarefa específica: calcular e devolver o quadrado de um valor x. Na definição deste procedimento, o valor a elevar ao quadrado, por poder ser um valor numérico qualquer, foi representado simbolicamente por x. Diz-se, por isso, que x é um parâmetro do procedimento quadrado, neste caso, até se trata do único parâmetro do procedimento. Numa fase posterior, ou seja, depois do procedimento estar completamente definido, a tarefa que lhe está associada será executada quando o procedimento é chamado. A chamada do procedimento quadrado faz-se colocando entre parêntesis o nome do procedimento, seguido do valor que se pretende processar e que será associado ao parâmetro. Esse valor, associado ao parâmetro, é geralmente designado por argumento.

> (quadrado 5) 25

Na chamada (quadrado 5), o valor 5 é o argumento. Este valor será associado ao parâmetro x, sendo devolvido (* 5 5) igual a 25, pois a tarefa executada corresponde a (* x x). Notar o seguinte: Na definição do procedimento quadrado, chamámos parâmetro a x, enquanto que na chamada do mesmo procedimento, chamámos argumento ao valor a associar a x. Um procedimento, por si só, não faz nada. Trata-se apenas de uma porção de texto, mais ou menos legível. Apenas, ao ser chamado, o procedimento gera no interior do computador um processo, o qual vai requerer os recursos computacionais necessários

Page 6: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 6

para a execução da tarefa que lhe está associada. O processo toma, como recursos, espaço de memória para os dados (no último exemplo, espaço de memória fundamentalmente para x) e toma também tempo do processador para os cálculos necessários. Podemos imaginar o processo gerado pela chamada (quadrado 5) e os

respectivos recursos computacionais, representados pelo rectângulo da figura. No final da chamada, o processo devolve o resultado calculado, 25, e morre, libertando os recursos computacionais que tinha tomado. A este assunto voltaremos em próximo capítulo, onde se procurará avaliar os recursos que cada processo requer de uma forma um pouco mais rigorosa.

5

quadrado

x : 5

( * x x)

25 Vejamos outra chamada do procedimento quadrado, com a consequente criação de um novo processo, idêntico ao anteriormente descrito.

> (quadrado (+ 1 3)) 16

Nesta chamada, o valor da expressão (+ 1 3) é associado a x, sendo devolvido o valor de (* 4 4) igual a 16. Depois deste exemplo, é apresentada a forma genérica para definir um procedimento:

(define nome-do-procedimento (lambda (parâmetro-1 parâmetro-2 ...) corpo-do-procedimento ))

O procedimento primitivo lambda também é uma forma especial do Scheme, e a sua regra de cálculo é:

⇒ Os identificadores que se encontram a seguir a lambda, entre parêntesis, representam valores genérico e são designados por parâmetros do procedimento;

⇒ lambda devolve o procedimento definido pelo programador, com os parâmetros referidos e ao qual ficará associada a tarefa especificada em corpo-do-procedimento.

Assim sendo, a forma especial define associa ao identificador nome-do-procedimento o procedimento especificado pelo programador em corpo-do-procedimento. Por exemplo, o nome quadrado ficou ligado a um procedimento, com o parâmetro x, cujo corpo é (* x x).

(define quadrado ; quadrado é o nome do procedimento (lambda (x) ; x é o parâmetro do procedimento (* x x))) ; (* x x) é o corpo do procedimento

Depois da definição de um procedimento, segue-se a regra de cálculo da chamada. (nome-do-procedimento argumento-1 argumento-2 ...)

Page 7: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 7

⇒ Em primeiro, são calculados os argumentos que acompanham nome-do-procedimento;

⇒ Seguidamente, no corpo do procedimento, os valores dos argumentos substituem os parâmetros respectivos (argumento-1 substitui parâmetro-1, argumento-2 substitui parâmetro-2, ...);

⇒ Finalmente, é devolvido o valor da última expressão calculada no corpo-do-procedimento.

É agora apresentada uma outra chamada do procedimento quadrado, na qual o cálculo do argumento implica uma outra chamada de quadrado.

> uadrado (quadrado (+ 3 2))) (q625

Neste caso, são criados dois processos do procedimento quadrado que, no entanto, não existem simultaneamente. O processo representado pelo rectângulo superior estará morto, quando o segundo estiver activo. A chamada em questão provocou a sequência de operações seguinte:

25

25

(+ 3 2)

(quadrado (quadrado (+ 3 2)))quadrado

x : 25

( * x x)625

quadrado

x : 5

( * x x)

> (quadrado (quadrado (+ 3 2))) (quadrado (quadrado 5)) (quadrado (* 5 5)) (quadrado 25) (* 25 25) 625

> (Exercício 1.2) Escrever em Scheme o procedimento soma-os-dois-e-tira 5 com dois parâmetros. De acordo com o próprio nome, recebe dois valores como argumentos, calcula a soma dos dois e retira-lhe 5.

-

> (soma-dois-e-tira-5 10 3) 8 > (soma-dois-e-tira-5 10 -3) 2

> (Exemplo 1.1) Segue-se a definição do procedimento soma-dos-quadrados que toma dois valores como argumentos e devolve a soma dos quadrados desses valores.

O procedimento pedido pode ser visto com dois parâmetros, x e y, recorrendo duas vezes ao procedimento quadrado, previamente definido. É isto que se pretende esboçar na figura.

x x2 y y2

x y

quadradoquadrado

soma-quadrados Este tipo de figura ou diagrama de fluxo de dados tem a virtude de mostrar a relação estabelecida entre os procedimentos utilizados e, sobretudo, põe em evidência os dados trocados entre eles. Recomenda-se a utilização destes diagramas quando a experiência de programação é pequena ou perante situações de complexidade elevada.

Page 8: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 8

; Procedimento com dois parâmetros, x e y. ; Devolve a soma dos quadrados de x e y. ; (define soma-dos-quadrados (lambda (x y) (+ (quadrado x) (quadrado y))))

O procedimento soma-dos-quadrados, por ter dois parâmetros receberá, em cada chamada, dois argumentos.

> (soma-dos-quadrados 1 2) 5 > (soma-dos-quadrados 5 (* 7 2)) 221

> (Exercício 1.3)

Apresentar o resultado e a sequência de operações com origem na chamada:

(soma-dos-quadrados 5 (soma-dos-quadrados 2 3)) Na definição de soma-dos-quadrados foi utilizado o procedimento quadrado, mas para isso, não seria necessário conhecer quadrado por dentro. Este procedimento pode ser visto como se fosse um bloco ou uma caixa-preta, em que entra um valor e sai o seu quadrado. Quando utilizámos quadrado, apenas nos interessou o que faz e não como o faz. Estamos perante um exemplo simples de uma Abstracção Procedimental. Outro aspecto interessante tem a ver com o facto de o procedimento quadrado utilizar x como nome do seu parâmetro, sem com isso impedir que soma-dos-quadrados utilizasse um parâmetro com a mesma designação x. Isto não causará qualquer confusão, pois os nomes dos parâmetros têm um significado muito bem localizado. Cada um deles apenas é reconhecido apenas no corpo do respectivo procedimento, sendo entidades distintas. Aliás, como vimos, sempre que o processo referente à chamada de um procedimento é criado, é reservado espaço próprio em memória para as entidades que irá processar, portanto, não se confundido com o espaço reservado por qualquer outro processo.

> (Exemplo 1.2) Pretende-se desenvolver um procedimento em Scheme para auxiliar os apostadores de Totoloto4 no preenchimento de boletins.

O procedimento gera sequências aleatórias de 6 inteiros, situados entre 1 e 49 e, nesta versão, não é feita a verificação de inteiros repetidos. Assim, se na sequência gerada de 6 inteiros algum deles aparecer repetido, o que não poderá acontecer numa aposta do Totoloto, o melhor será deitar fora essa sequência e pedir outra.

1 2 3 4 5 6 7

8 9 10 11 12 13 14

15 16 17 18 19 20 21

22 23 24 25 26 27 28

29 30 31 32 33 34 35

36 37 38 39 40 41 42

43 44 45 46 47 48 49

Neste procedimento, uma tarefa fácil de identificar é a geração aleatória de um inteiro entre 1 e 49, e é por ela que iremos começar. Para esta tarefa, vamos definir o procedimento designado por roleta-1-49 que não tem parâmetros.

4 Uma aposta do totoloto é uma sequência de 6 números não repetidos, situados entre 1 e 49.

Page 9: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 9

; Procedimento sem parâmetros. ; Devolve um inteiro entre 1 e 49, determinado aleatoriamente. ; (define roleta-1-49 (lambda () (+ 1 (random 49))))

No corpo do procedimento roleta-1-49 é utilizada uma chamada ao procedimento random5, (random 49), que devolve um inteiro aleatório entre 0 e 48. Adicionando-lhe 1, resulta um inteiro entre 1 e 49, como se pretendia.

> (roleta-1-49) 33 > (roleta-1-49) 8

O procedimento roleta-1-49 não tem parâmetros e por isso é chamado colocando o seu nome entre parêntesis, isolado e sem qualquer argumento. Este procedimento só pode ser utilizado para gerar números entre 1 e 49. E se se pretendesse, por exemplo, gerar números aleatórios entre 1 e 6, para simular o lançamento de um dado? Parece que seria necessário escrever um novo procedimento, provavelmente com o nome roleta-1-6.

; Procedimento sem parâmetros. ; Devolve um inteiro entre 1 e 6, determinado aleatoriamente. ; (define roleta-1-6 (lambda () (+ 1 (random 6))))

Mas uma solução mais flexível teria sido definir, em vez de roleta-1-49 e roleta-1-6, por exemplo, roleta-1-n com um parâmetro n, para gerar aleatoriamente um inteiro entre 1 e n.

; Procedimento com o parâmetro n. ; Devolve um inteiro entre 1 e n, determinado aleatoriamente. ; (define roleta-1-n (lambda (n) (+ 1 (random n))))

Com este procedimento torna-se fácil simular lançamentos de um dado.

> (roleta-1-n 6) 5 > (roleta-1-n 6) 3

Mas também seria fácil simular a geração de números aleatório entre 1 e qualquer outro inteiro positivo. Por exemplo, para gerar um número do Totoloto:

> (roleta-1-n 49) 27

5 O procedimento random não faz parte da definição normalizada do Scheme e pode apresentar-se com especificações diferentes para diferentes implementações. No DrScheme, random tem um argumento que deverá situar-se entre 1 e 231-1, ou seja, entre 1 e 2147483647. A chamada (random n) devolve um inteiro aleatório entre 0 e n-1.

Page 10: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 10

Retomemos o procedimento roleta-1-49, e com ele definamos o procedimento aposta para gerar, por cada chamada, uma aposta de Totoloto. A chamada (aposta) não inclui argumentos, pois este procedimento vai ser definido sem parâmetros.

1 2 3 4 5 6 7

8 9 10 11 12 13 14

15 16 17 18 19 20 21

22 23 24 25 26 27 28

29 30 31 32 33 34 35

36 37 38 39 40 41 4243 44 45 46 47 48 49

> (aposta) Numero 1: 43 Numero 2: 3 Numero 3: 41 Numero 4: 32 Numero 5: 40 Numero 6: 10

Vejamos outra chamada do procedimento aposta e a correspondente aposta gerada.

1 2 3 4 5 6 7

8 9 10 11 12 13 14

15 16 17 18 19 20 21

22 23 24 25 26 27 28

29 30 31 32 33 34 35

36 37 38 39 40 41 4243 44 45 46 47 48 49

> (aposta) Numero 1: 49 Numero 2: 32 Numero 3: 6 Numero 4: 26 Numero 5: 19 Numero 6: 22

Verificar que do procedimento aposta não se espera a devolução de um valor, mas apenas um conjunto de mensagens no ecrã.

1..49 1..49 1..49 1..49 1..49

aposta

roleeta-1-49 rolroleta-1-49

1..49

ta-1-49roleeta-1-49 roleta-1-49 rolta-1-49

Uma solução possível, mas muito repetitiva, para o procedimento aposta é esboçada no diagrama de fluxo de dados e seguidamente apresentada6.

; Procedimento sem parâmetros. ; O valor devolvido pelo procedimento não tem qualquer interesse. Deste, apenas se ; espera um conjunto de mensagens no ecrã, que representa uma aposta do Totoloto. ; (define aposta (lambda () (display "Numero 1: ") (display (roleta-1-49)) (newline) (display "Numero 2: ") (display (roleta-1-49)) (newline) (display "Numero 3: ") (display (roleta-1-49)) (newline) (display "Numero 4: ") (display (roleta-1-49)) (newline) (display "Numero 5: ") (display (roleta-1-49)) (newline) (display "Numero 6: ") (display (roleta-1-49)) (newline)))

6 Por agora, serve esta solução. Atendendo ao seu carácter repetitivo, deverá ser possível encontrar uma solução mais compacta.

Page 11: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 11

Do procedimento primitivo display, utilizado em aposta para visualizar dados, também não se espera um valor para ser posteriormente processado, mas sim um efeito lateral, ou seja, a visualização no ecrã de um valor numérico, como em (display (roleta-1-49)), ou a visualização de uma cadeia de caracteres, indicada entre aspas, como em (display "Numero 1: "). Sendo nova-linha a tradução do procedimento primitivo newline, fica obviamente esclarecida a sua funcionalidade: A visualização passa para o início da linha seguinte. Na tentativa de encontrar uma solução mais compacta, verifica-se que a tarefa associada ao procedimento aposta poderá ser vista como a repetição de uma sub-tarefa, seis vezes. De facto, para gerar uma aposta do Totoloto é necessário gerar e visualizar seis números, situados entre 1 e 49, o que permite imaginar uma tarefa auxiliar que consistirá no seguinte:

i

aposta-aux

roleta-1-49

1..49 1. Visualizar o texto "Numero ", seguido do valor associado a um parâmetro designado por i (valor de 1 a 6). 2. Visualizar o texto ": ", seguido de um número aleatório entre 1 e 49. 3. Mudar de linha

Parece assim justificar-se a definição de um procedimento auxiliar, designado por aposta-aux, e que se ocupe desta sub-tarefa.

; Procedimento auxiliar do procedimento aposta, com o parâmetro i. ; Visualiza no ecrã uma das 6 linhas (a linha i) de uma aposta do Totoloto. ; (define aposta-aux (lambda (i) (display "Numero ") (display i) (display ": ") (display (roleta-1-49)) (newline)))

O procedimento aposta poderá agora tomar outra forma, mais compacta, designada por aposta-melhorada, que se baseia na utilização de aposta-aux. O procedimento aposta-melhorada chama aposta-aux 6 vezes. A primeira com o argumento 1, a segunda com o argumento 2, e assim sucessivamente até à sexta chamada com o argumento 6.

2 3 4 5 6

aposta-melhorada

1

apoaposta-aux aposta-auxaposta-aux

aposta-aux sta-auxaposta-aux

O diagrama de fluxo de dados não precisa de mostrar a ligação de aposta-aux a roleta-1-49, pois estamos apenas interessados em saber "o que faz" aposta-aux e não "como faz". O procedimento aposta-aux surge assim como uma caixa-preta.

; versão melhorada do procedimento aposta. ; (define aposta-melhorada (lambda () (aposta-aux 1)

Page 12: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 12

(aposta-aux 2) (aposta-aux 3) (aposta-aux 4) (aposta-aux 5) (aposta-aux 6)))

> (Exercício 1.4) Para pavimentar um parque desportivo utilizaram-se peças quadradas de dois tipos, umas de lado de comprimento lado1 e outras de lado de comprimento lado2. Escrever o procedimento area com os parâmetros n1, lado1, n2 e lado2, em que n1 e n2 representam o número de peças de cada tipo, e devolve a área pavimentada. A chamada para uma situação de 200 peças de lado de comprimento 5 e 400 de lado de comprimento 10, seria:

> (area 200 5 400 10) 45000

Na escrita de area, sugere-se a utilização do procedimento quadrado, que recebe um valor e devolve-o elevado ao quadrado. Apresentar o diagrama de fluxo de dados que reflicta a ligação entre os procedimentos utilizados.

> (Exercício 1.5)

Escrever o procedimento area-losango-inscrito com os parâmetros lado1 e lado2, que devolve a área do losango inscrito no rectângulo, cujos lados são os parâmetros referidos.

> (area-losango-inscrito 20 10) 100 Apesar de não ser a melhor ideia, considerar como pista que a área de um losango corresponde à área de 4 triângulos rectângulos7 iguais, pelo que se sugere a utilização de um procedimento auxiliar que calcule a área deste tipo de triângulo. Apresentar o diagrama de fluxo de dados que reflicta a ligação entre os procedimentos utilizados.

> (Exercício 1.6)

Escrever o procedimento area-sombreada com os parâmetros lado1 e lado2, que devolve a área sombreada no rectângulo, cujos lados são os parâmetros.

> (area-sombreada 20 10) 70.0 Considerar como pista que a área sombreada no rectângulo corresponde à soma da área de vários triângulos rectângulos. Apresentar o diagrama de fluxo de dados que reflicta a ligação entre os procedimentos utilizados.

7 Os triângulos rectângulos têm um dos ângulos igual a 90º.

Page 13: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 13

> sec1-5 Variáveis locais

A definição de variáveis locais, no interior dos procedimentos, para além de facilitar a leitura desses procedimentos, pode ainda eliminar cálculos repetidos. Para clarificar este assunto, comecemos por analisar um exemplo. Um procedimento recebe o comprimento dos lados de um triângulo e determina o seu perímetro e a percentagem de cada lado em relação ao perímetro. Para melhor se entender o que faz o referido procedimento, designado por percentagem-lado-perimetro, analisemos o seu comportamento em duas situações.

> (percentagem-lado-perimetro 10.0 15.0 20.0) perimetro do triangulo: 45.0 22.222222222222 33.333333333333 44.444444444444

Em primeiro lugar é visualizado o perímetro do triângulo, seguido das percentagens do comprimento de cada lado em relação ao perímetro.

> (percentagem-lado-perimetro 15.0 15.0 15.0) perimetro do triangulo: 45.0 33.333333333333 33.333333333333 33.333333333333

Na solução que se segue, o cálculo do perímetro, (+ a b c), é repetido quatro vezes!...

; Procedimento com 3 parâmetro que representam os lados de um triângulo. ; O valor devolvido por este procedimento não tem qualquer interesse. ; Deste procedimento apenas se espera um conjunto de mensagens no ecrã ; correspondentes ao perímetro do triângulo e ; à percentagem de cada um dos lado em relação ao perímetro. ; (define percentagem-lado-perimetro-1 (lambda (a b c) (display "perimetro do triangulo: ") (display (+ a b c)) (newline) (display (* 100 (/ a (+ a b c)))) (newline) (display (* 100 (/ b (+ a b c)))) (newline) (display (* 100 (/ c (+ a b c))))))

Para evitar repetições deste tipo, bastaria definir uma variável local, no corpo do procedimento, com o valor correspondente ao cálculo repetido, pronta a ser utilizada sempre que fosse necessária. Esta hipótese é possível com let, uma outra forma especial do Scheme. A solução que se segue, percentagem-lado-perimetro-2, onde se define localmente a variável perimetro, é mais eficiente que a anterior, pois elimina o cálculo repetido do perímetro, para além de se tornar mais legível.

; Versão melhorada do procedimento percentagem-lado-perimetro-1. ; Define-se, localmente com let, a variável perimetro. ; (define percentagem-lado-perimetro-2 (lambda (a b c)

Page 14: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 14

(let ((perimetro (+ a b c))) (display "perimetro do triangulo: " (display perimetro) (newline) (display (* 100 (/ a perimetro))) (newline) (display (* 100 (/ b perimetro))) (newline) (display (* 100 (/ c perimetro)))))

O rectângulo assinala o correconhecido o identificador pe Analisemos com cuidado a fo

(let ( (nome-1 express (nome-2 express ( ... corpo-de-let )

Notar duas áreas distintas nesão associados aos identificrespectivas, expressão-1, expresidentificadores são reconhecid

> (Exercício 1.7) Analisar o procedimento ex

; Procedimento para ilustrar a utilização; (define experiencia-com-let (lambda (x y) (let ((local1 (+ x y)) (local2 (* x y))) (/ (+ local1 local2) (* local1 local2))))

Indicar como responde o Sch

> (experiencia-com-let ?? > experiencia-com-let (??

Voltando ao exemplo percentaintroduz um segundo nível dpassa a ser possível utilizar a com visibilidade num espaçoperc-b e perc-c.

; Versão melhorada do procedimento percen; Define, localmente com let, a variável ; num nível mais interno, as variáveis re

perimetro

)

)

po de let que, neste caso, representa o local onde é rimetro.

rma geral da expressão let:

ão-1) ão-2) ) )

sta forma. Numa das áreas, definida entre parêntesis, adores nome-1, nome-2, ..., os valores das expressões são-2, ... . Na outra área, designada por corpo-de-let, os os e podem ser aí utilizados.

periencia-com-let que se segue:

de let

eme nas situações que se apresentam. 3 7)

-3 7)

gem-lado-perimetro-2, apresenta-se uma outra solução que e let, dentro do corpo de let já existente. Desta forma, variável local perimetro na definição de outras variáveis, ainda mais restrito. Referimo-nos às variáveis perc-a,

tagem-lado-perimetro-2. perimetro e também, lativas às percentagens.

Page 15: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 15

; (define percentagem-lado-perimetro-3 (lambda (a b c) (let ((perimetro (+ a b c))) (let ((perc-a (* 100 (/ a perimetro)) (perc-b (* 100 (/ b perimetro)) (perc-c (* 100 (/ c perimetro)) (display "perimetro do triangulo: " (display perimetro) (newline) (display perc-a) (newline) (display perc-b) (newline) (display perc-c)))))

Já foi dito que os parâmetros reconhecidas no corpo do proca, b, e c do procedimento percentprocedimentos, representando com os lados de um triângulo. Ccom um campo de acção ainda mAs entidades criadas com let sónão na totalidade do corpo dperimetro-3, os parâmetros a, b, e corpo do procedimento. No enprimeiro let, representado pelo rsegundo let, ainda mais limitado,

> (Exercício 1.8) A conversão de uma temCentígrados pode ser realizaoutro lado, para converter umKelvin bastará somar 273.16. Escrever o procedimento convertemperatura em graus Fahrenhe

> (converte-Fahrenheit 14Fahrenheit: 14 Centigrados: -10 Kelvin: 263.16

> (Exemplo 1.3)

A fórmula de Briggs8 permitee c de um triângulo, os seus semi-perímetro do triângulo, Escrever em Scheme o procedimum triângulo e visualiza os seus

8 Henry Briggs foi um matemático ingGresham House, em Londres.

perimetro

) ) ))

)

de um edimentoagem-ladoentidadesom let tais restr

são reco procedc são recotanto, peectângul correspo

peraturda atrava tempe

te-Fahrenhit e respo)

calculartrês ângou seja (ento desitrês ângu

lês (1561-1

perc-a, perc-b, perc-c

procedimento são entidades locais, apenas . Por este facto, os nomes dos parâmetros

-perimetro-3, podem ser re-utilizados noutros que, em princípio, não terão nada a ver ambém se criam entidades locais, mas estas ito que o dos parâmetros do procedimento.

onhecidas no corpo desta forma especial e imento. Por exemplo, em percentagem-lado-nhecidos e podem ser utilizados em todo o

rimetro apenas é reconhecido no espaço do o maior, e perc-a, perc-b, e perc-c no espaço do ndente ao rectângulo menor.

a em graus Fahrenheit para graus és da fórmula Tc = (F - 32) x 5/9. Por ratura em graus Centígrados para graus

eit com o parâmetro tf que representa uma nde como se indica:

, a partir do comprimento dos lados a, b ulos internos α, β e γ. Na figura, sp é o a + b + c)/2. gnado por briggs que recebe os três lados de los internos.

631) e o primeiro professor de geometria no

Page 16: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 16

cacspasp

*)(*)(

2sin −−

cbcspbsp

*)(*)(

2sin −−

ba*2sin =

bspasp )(*)( −−γ

> (briggs 10.0 10.0 10.0) O triangulo com os lados de comprimento: 10.0, 10.0, 10.0 tem os seguintes angulos: 60.00000000000001, 60.00000000000001, 60.000000000000019 > (briggs 10.0 15.0 15.0) O triangulo com os lados de comprimento: 10.0, 15.0, 15.0 tem os seguintes angulos: 38.94244126898138, 70.52877936550931, 70.52877936550931

O procedimento briggs traz algumas novidades, com a introdução de funções trigonométricas. Por exemplo, uma destas funções é asin10 que aceita o valor de um seno e devolve o arco respectivo. Trabalha em radianos e não em graus, justificando por isso a conversão de radianos para graus, realizada por radians->degrees11. No primeiro let, são definidos o semi-perímetro sp e os produtos designados por ab = a * b, ac = a * c e bc = b * c. Depois, no corpo do primeiro let, e já com sp definido, num segundo let, são definidos spa = sp - a, spb = sp - b e spc = sp - c. Finalmente, num terceiro let, são definidos os três ângulos, segundo a fórmula de Briggs.

; Procedimento com 3 parâmetro que representam os lados de um triângulo. ; O valor devolvido por este procedimento não tem qualquer interesse. ; Deste procedimento apenas se espera um conjunto de mensagens no ecrã ; que descrevem os ângulos internos do triângulo. ; (define briggs (lambda (a b c) (let ((sp (/ (+ a b c) ; definição de sp (semi-perímetro) e 2)) ; dos produtos (ab (* a b)) ; ab = a*b (ac (* a c)) ; ac = a*c (bc (* b c))) ; bc = b*c (let ((spa (- sp a)) ; sp, depois de definido, é utilizado na (spb (- sp b)) ; definição de outras variáveis locais (spc (- sp c))) (let ((ang1 (radians->degrees (* 2 (asin (sqrt (/ (* spb spc) bc)))))) (ang2 (radians->degrees (* 2 (asin (sqrt (/ (* spa spc) ac)))))) (ang3 (radians->degrees (* 2 (asin (sqrt (/ (* spa spb) ab))))))) (display "O triangulo com os lados de comprimento: ") (display a) (display ", ") (display b)

9 Deveria ser: 60.0, 60.0, e 60.0, para que da soma dos 3 ângulos internos resultasse 180º. Assim não acontece devido a arredondamentos nos cálculos. 10 asin significa arco cujo seno é… 11 Nem todas as implementações de Scheme disponibilizam radians->degrees e degrees->radians, o mesmo acontecendo com a constante pi. Por este facto, optou-se por inclui-los na escrita do procedimento.

Page 17: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 17

(display ", ") (display c) (newline) (display "tem os seguintes angulos: ") (display ang1) (display ", ") (display ang2) (display ", ") (display ang3) (newline)))))) ; ; Procedimento que converte radianos em graus ; (define radians->degrees (lambda (ang) (/ (* ang 180) pi))) ; (define pi 3.141592653589793)

> (Exercício 1.9) A área de um triângulo pode determinar-se a partir do comprimento dos seus lados a, b, e c, com a fórmula que se apresenta, em que sp é o semi-perímetro do triângulo. Escrever o procedimento area-triangulo que tem como parâmetros os três lados de

um triângulo e devolve a sua área. Sugere-se a definição de uma variável local sp para evitar a repetição do cálculo do semi-perímetro.

)(*)(*)(* cspbspaspsptriarea −−−=−

> (Exercício 1.10)

Para determinar o dia da semana de uma data do calendário utiliza-se um algoritmo que se vai descrever. Antes disso, considere-se:

• m o mês do ano, em que Março é o mês 1, Abril 2, até Dezembro que é o mês 10. Janeiro e Fevereiro são considerados os meses 11 e 12 do ano anterior12.

• d o dia do mês. • a o ano do século. • s o século anterior13. Por exemplo, para 4 de Julho de 1989 seria m=5, d=4, a=89, s=19. Por outro lado, para 4 de Janeiro do mesmo ano seria m=11, d=4, a=88, s=19.

Vejamos agora os passos do algoritmo. Seja: • mint a parte inteira de (13m-1)/5. • aint a parte inteira de a/4. • sint a parte inteira de s/4. • x = mint+aint+sint+d+a-2s. • dia o resto da divisão inteira x/7.

dia é a resposta, de acordo com a identificação seguinte: dia=0 é o Domingo, dia=1 é 2ª-feira, e assim sucessivamente até dia=6 que corresponde a Sábado.

12 Esta identificação dos meses, perfeitamente anormal, é apenas utilizada dentro do algoritmo. 13 Mais uma identificação anormal, para utilizar no algoritmo.

Page 18: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 18

Escrever o programa dia-da-semana que, em relação a uma data, pede o dia, mês e ano e responde com o respectivo dia da semana. Na chamada que se segue, a data em causa é 18 de Agosto de 2001.

> (dia-da-semana) dia: 18 mes: 8 ano: 2001 O dia da semana e' 6

> (Exemplo 1.4)

Pretende-se definir o procedimento circulo, sem parâmetros, que principia por pedir o raio de um círculo. O procedimento termina, visualizando no ecrã a área co círculo e o respectivo perímetro.

> culo) (cirraio:

Este é o primeiro exemplo em que o utilizador é convidado a fornecer dados através do teclado. A mensagem raio: indica que o procedimento espera a resposta do utilizador, neste caso, o valor do raio do círculo, seguido da actuação da tecla return. Seja 10 o valor fornecido… e a resposta é dada de imediato.

read area-cir

circulo

r perimetro r r area

perimetro-cir

perimetro = 2 x pi x r area= pi x r2

r

> (circulo) raio: 10 Area do circulo e': 314.1592653589793 Perimetro do circulo e': 62.83185307179586 Na figura é esboçado o diagrama de fluxo de dados do procedimento circulo, em que se põe em evidência mais três procedimentos. Dois deles são procedimentos auxiliares que acompanham o procedimento circulo. O restante, read, trata-se de um procedimento fornecido pelo Scheme.

; Procedimento sem parâmetros. ; Pede o valor do raio de um círculo, a fornecer através do teclado. ; O valor devolvido por este procedimento não tem qualquer interesse. ; Deste procedimento apenas se espera um conjunto de mensagens no ecrã ; que definem a área e o perímetro do círculo. ; (define circulo (lambda () (display "raio: ") (let ((raio (read))) (display "Area do circulo e': ") (display (area-cir raio)) (newline) (display "Perimetro do circulo e': ") (display (perimetro-cir raio))))) ;

Page 19: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 19

; Procedimento auxiliar. Recebe o raio de um círculo e devolve a sua área. ; (define area-cir (lambda (r) ; area do círculo = pi * r * r (* pi r r))) ; ; Procedimento auxiliar. Recebe o raio de um círculo e ; devolve o seu perímetro. ; (define perimetro-cir (lambda (r) ; perimetro do círculo = 2 * pi * r (* 2 pi r))) ; (define pi 3.141592653589793)

Na implementação do procedimento circulo, o procedimento read foi utilizado no contexto de uma construção let, (let ((raio (read))). Aqui, read surge como um procedimento primitivo sem parâmetros que espera um valor a ser fornecido através do teclado. Este tipo de situação é geralmente antecedida da visualização de uma mensagem, neste caso (display "raio: "), informando o utilizador que deve fornecer um determinado dado, através do teclado. A definição de uma variável local com o valor devolvido por read é uma prática usual. Se assim não fosse este valor ou era imediatamente utilizado (por exemplo, numa expressão) ou perder-se-ia, não podendo ser utilizado uma segunda vez.

> sec1-6 Estruturas de Selecção

São frequentes as situações que exigem a tomada de decisões onde, perante várias hipóteses, tem que se optar por uma delas. Por exemplo, se se pretende simular o sorteio de 6 números do Totoloto, em vez de repetir 6 vezes a escrita de um certo conjunto de instruções, aliás como foi feito no Exemplo 1.1, teria sido preferível programar algo do tipo:

• Sortear mais um número; • Se ainda não foram sorteados 6 números, repete-se a acção anterior. Caso

contrário, acabou de ser apurada uma aposta, não sendo necessário sortear mais números.

Mas vejamos outro exemplo, que simula o lançamento de um projéctil no espaço. Se o vector vec representar a velocidade inicial do projéctil lançado da origem dos eixos e ang o ângulo de lançamento, pretende-se que o projéctil não seja lançado para “trás”. Então, ang deverá ser menor que 90º. Para se considerar esta condição, poderíamos escrever: (if (< ang 90) (faz-o-lançamento ...) (display "projectil mal orientado"))

Nesta expressão if, surge uma expressão de relação, (< ang 90), cujo resultado pode apenas assumir 2 valores, #t (verdadeiro) e #f (falso):

Page 20: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 20

⇒ #t, se ang for menor que 90 ⇒ #f, se ang for maior ou igual que 90.

As entidades com valores #t e #f são designadas de booleanas e as expressões de que resultam booleanos são designadas de predicados. Por exemplo, (< 30 40) é um predicado com valor #t, pois 30 é menor que 40, e (< 30 30) é um predicado com valor #f, pois 30 não é menor que 30. Identifica-se assim mais uma forma especial do Scheme, if:

(if expressão-predicado expressão-consequente expressão-alternativa)

A regra de cálculo da forma especial if é a seguinte: ⇒ Calcular a expressão-predicado; ⇒ Se resultar #t, é calculada a expressão-consequente; ⇒ Se resultar #f, é calculada a expressão-alternativa.

Os procedimentos de relação disponibilizadas pelo Scheme são: > (maior) , < (menor), = (igual), >= (maior ou igual), e <= (menor ou igual).

> (if (> 5 12) 5 14

(* 2 7))

> (if (<= 5 12) 5 5 (* 2 7))

Retomando o exemplo do lançamento do projéctil. Pretende-se agora garantir que o lançamento só deverá ocorrer se o ângulo se situar entre 20 e 70º. Para se considerar esta nova condição, podemos escrever: (if (and (> ang 20) (< ang 70)) (faz-o-lançamento ...) (display "projectil mal orientado"))

A expressão-predicado é, neste exemplo, uma expressão lógica que, como acontecia com as expressões de relação, também origina resultados booleanos.

Os procedimentos lógicos são especialmente indicados para definir condições compostas.

(if (and (>= altura 160) (<= altura 180)) (display "Altura média") (display "Ou muito alto ou muito baixo!!!"))

Os procedimentos lógicos disponibilizadas pelo Scheme são: and (e), or (ou), not (não).

Page 21: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 21

Faz parte da cultura Scheme terminar com ? o nome dos procedimentos que são predicados, ou seja, que devolvem valores booleanos. O próprio Scheme dá o exemplo, com os predicados que disponibiliza: negative?, positive?, zero?, even?, odd?, boolean?, symbol?, procedure?, number?, integer?, real? e outros. Nesta altura, recomenda-se uma consulta ao Anexo A, com o objectivo de se verificar a funcionalidade de cada um destes predicados, bem como dos operadores lógicos e de relação.

> (Exercício 1.11) Modificar a solução apresentada para o procedimento circulo do Exemplo 1.4, que verifica se o utilizador fornece um valor numérico ao responder com o comprimento do raio. O diálogo passará a revestir a seguinte forma:

> (circulo) raio (indicar um valor numérico positivo): dez Erro: Deve indicar um valor numérico positivo. > (circulo) raio (indicar um valor numérico positivo): -10.5 Erro: Deve indicar um valor numérico positivo. > (circulo) raio (indicar um valor numérico positivo): 10 Area do circulo e': 314.1592653589793 Perimetro do circulo e': 62.83185307179586

> (Exercício 1.12)

Relembrar o exemplo 1.9 e considerar que os comprimentos a, b e c fornecidos como argumentos podem não corresponder aos lados de um triângulo, bastando que qualquer um deles seja igual ou superior à soma dos outros dois. Escrever o procedimento area-triangulo-melhorada que devolve 0, em vez da área, sempre que detecta este tipo de situação. Sugere-se a utilização de um procedimento auxiliar para validar se os comprimentos fornecidos correspondem ou não aos lados de um triângulo. Apresentar o diagrama de fluxo de dados que reflicta a ligação entre os procedimentos utilizados.

Retomando, mais uma vez, o exemplo do lançamento do projéctil, pretende-se agora garantir os seguintes tipos de lançamento:

• Se ang maior que 70º ou menor ou igual que 10º, não haverá lançamento;

• Se ang menor ou igual que 70º e maior que 50º, haverá um lançamento a grande altitude;

• Se ang menor ou igual que 50º e maior que 30º, haverá um lançamento a média altitude;

• Se ang maior ou igual que 30º e maior que 10º, haverá um lançamento a baixa altitude.

Page 22: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 22

Para ter em conta todas estas condições, definiu-se o procedimento projectil. Verificar que neste a expressão-alternativa do primeiro if é, ela própria, um novo if…

(define projectil (lambda (ang) (if (or (> ang 70) (<= ang 10)) (display "projectil mal orientado") (if (> ang 50) (display "lancamento a grande altitude") (if (> ang 30) (display "lancamento a media altitude") (display "lancamento a baixa altitude"))))))

> (projectil 10) projectil mal orientado > (projectil 40) lancamento a media altitude > (projectil 70) lancamento a grande altitude > (projectil 120) projectil mal orientado

Não se poderá dizer que o procedimento projectil, baseado numa sequência de if, seja muito legível. Entende-se o que faz, mas em situações como esta, é preferível utilizar a forma especial cond:

(define projectil-melhorado (lambda (ang) (cond ((or (> ang 70) (<= ang 10)) (display "projectil mal orientado")) ((> ang 50) (display "lancamento a grande altitude")) ((> ang 30) (display "lancamento a media altitude")) (else (display "lancamento a baixa altitude")))))

Identificando a forma especial do Scheme cond:

(cond (predicado-1 exp1-1 exp1-2 ...) ; cláusula 1 (predicado-2 exp2-1 exp2-2 ...) ; cláusula 2 ... (else exp-else-1 exp-else-2 ...) ) ; cláusula else

A regra de cálculo da forma especial cond é a seguinte:

⇒ Calcular os predicados, começando por predicado-1, até encontrar um predicado com valor #t;

⇒ Logo que se encontre um predicado #t, calcular as expressões correspondentes;

⇒ Se não se encontrar qualquer predicado com valor #t, calcular as expressões correspondentes a else.

⇒ Nota: A cláusula else é opcional. Se não existir e se do cálculo de todos os predicados resultar #f, nenhuma das expressões de cond será calculada.

Page 23: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 23

Sobre as formas especiais if e cond poder-se-á dizer que if é de evitar em situações com mais de duas opções, por se tornar de mais difícil leitura. E mesmo com duas opções, é também de evitar if quando a expressão-consequente ou a expressão-alternativa integram mais do que uma expressão, situação que obriga à utilização de begin.

(if expressão-predicado (cond (expressão-predicado (begin expressão-consequente-1 expressão-consequente-1 expressão-consequente-2 expressão-consequente-2 ... ... expressão-consequente-m) expressão-consequente-m) (begin (else expressão-alternativa-1 expressão-alternativa-1 expressão-alternativa-2 expressão-alternativa-2 ... ... expressão-alternativa-n) ) expressão-alternativa-n) )

begin é mais uma das formas especiais do Scheme, que se apresenta da seguinte maneira: (begin expressão-1 expressão-2 ... expressão-n). begin garante que estas expressões são calculadas em sequência, desde a primeira até à última, e devolve o valor da última expressão. Este tipo de sequência está implícito no corpo dos procedimentos quando contém mais do que uma expressão e também nas cláusulas de cond.

> (Exemplo 1.5) Apresentam-se duas versões de um procedimento que recebe dois valores e visualiza a relação de grandeza entre eles. Na versão comparador-com-if recorre-se a if, e utiliza-se cond, na versão comparador-com-cond. Ambos respondem da mesma maneira e diferem apenas no grau de legibilidade que oferecem.

(define comparador-com-if (lambda (x y) (if (> x y) (begin (display x) (display " e' maior que ") (display y)) (if (> y x) (begin (display y) (display " e' maior que ") (display x)) (begin (display "ambos iguais a ") (display x))))))

> -if 2 3) (comparador-com3 e' maior que 2 > (comparador-com-if 3 2) 3 e' maior que 2 > (comparador-com-if 3 3) ambos iguais a 3

Page 24: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 24

(define comparador-com-cond (lambda (x y) (cond ((> x y) (display x) (display " e' maior que ") (display y)) ((> y x) (display y) (display " e' maior que ") (display x)) (else (display "ambos iguais a ") (display x)))))

> (Exercício 1.13) O procedimento rectangulo-maior tem como parâmetros lado-a1, lado-a2, lado-b1, e lado-b2, que correspondem ao comprimento dos lados de 2 rectângulo: Os dois primeiros do rectângulo A e os restantes do rectângulo B. Escrever este procedimento em Scheme que calcula a área de cada um dos rectângulos, compara-as e responde da seguinte maneira:

> (rectangulo-maior 10 20 15 5) Rectangulo A: 200 Rectangulo B: 75 O rectangulo A e' maior 125 unidades. > (rectangulo-maior 10 20 15 18) Rectangulo A: 200 Rectangulo B: 270 O rectangulo B e' maior 70 unidades. > (rectangulo-maior 10 20 40 5) Rectangulo A: 200 Rectangulo B: 200 Os rectangulos apresentam igual area.

> (Exercício 1.14) Idêntico ao exercício anterior, mas agora o procedimento não tem parâmetros. O comprimento de cada lado é fornecido através do teclado. Imaginar um diálogo apropriado e escrever o procedimento. Apresentar o diagrama de fluxo de dados que reflicta a ligação entre os procedimentos utilizados.

> sec1-7 Exercícios e Exemplos

Nesta secção são apresentados exercícios e exemplos para consolidação da matéria considerada no decorrer do capítulo. Recomenda-se o estudo dos exemplos e a resolução de alguns dos exercícios, em frente do computador, atitude que é fundamental tomar desde o início do processo de aprendizagem da programação. Estudar os exemplos, introduzir-lhes alterações, inventar e resolver novos exercícios são tarefas que deverão fazer parte dos planos de quem pretende dominar a arte de programar bem.

Page 25: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 25

Apesar de ainda muito limitados em termos do conhecimento das potencialidades do Scheme, é já possível resolver alguns problemas interessantes.

> (Exemplo 1.6) Os números decimais ímpares terminam em 1, 3, 5, 7 e 9. Vamos agora inventar uma nova classe de números, os ímpares-curvos (!!!) como sendo os números ímpares que terminam em 3, 5 e 9 (dígitos que, no respectivo desenho, usam segmentos curvos!). Considere o procedimento impar-curvo? que determina se um número é ou não ímpar-curvo.

> (impar-curvo? 2345) #t > (impar-curvo? 2346) #f > (impar-curvo? 2347) #f

Escrever em Scheme o procedimento impar-curvo? A solução que se apresenta começa por definir localmente a variável digito-menos-significativo, que se obtém calculando o resto da divisão inteira do número dado por 1014. Seguidamente, deduz-se se o número em questão é ou não impar-curvo, testando se digito-menos-significativo é 3, 5 ou 9.

(define impar-curvo? (lambda (num) (let ((digito-menos-signif (remainder num 10))) (cond ((= digito-menos-signif 3) #t) ((= digito-menos-signif 5) #t) ((= digito-menos-signif 9) #t) (else #f)))))

Uma outra solução é conseguida através de uma condição composta, que utiliza o operador lógico or.

(define impar-curvo? (lambda (num) (let ((digito-menos-signif (remainder num 10))) (or (= digito-menos-signif 3) (= digito-menos-signif 5) (= digito-menos-signif 9)))))

> (Exemplo 1.7) Supor que já se dispõe do procedimento quantos-positivos, com dois parâmetros. Este procedimento analisa os seus parâmetros e fornece como resultado 2, 1 ou 0, conforme o número de parâmetros positivos.

> (quantos-positivos 1 2) 2 > (quantos-positivos 1 -2) 1 > (quantos-positivos -1 -1) 0

14 O resto da divisão inteira x/y pode calcular-se com o procedimento primitivo remainder, fazendo (remainder x y). A este propósito, recomenda-se a consulta do Anexo A, em particular o que se refere a processamento numérico.

Page 26: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 26

Por seu turno, o procedimento soma-positivos também analisa os seus dois parâmetros: a soma

b

soma-positivos

quantos-positivos

a 1, 2, 0 b

• Se ambos forem positivos, devolve a soma dos dois; • Se apenas um for positivo, devolve o valor desse positivo; • Se ambos forem negativos, devolve o valor 0.

Escrever em Scheme o procedimento soma-positivos, utilizando o procedimento quantos-positivos, suposto já existente. Optou-se por criar localmente a variável numero-de-positivos, que vai conter o número de positivos em jogo, através de uma chamada ao procedimento quantos-positivos. O diagrama de fluxo de dados mostra a ligação existente entre os procedimentos utilizados.

(define soma-positivos (lambda (a b) (let ((numero-de-positivos (quantos-positivos a b))) (cond ((= numero-de-positivos 2) (+ a b)) ((zero? numero-de-positivos) 0) ((positive? a) a) (else b)))))

Por seu lado, o procedimento quantos-positivos baseia-se nos seguintes testes: x e y são ambos positivos; x e y são ambos negativos; se não for nenhum destes casos, então um dos argumentos será positivo.

(define quantos-positivos (lambda (x y) (cond ((and (positive? x) (positive? y)) 2) ((and (negative? x) (negative? y)) 0) (else 1))))

> (soma-positivos 3 2) 5 > (soma-positivos 3 -2) 3 > (soma-positivos -3 2) 2 > (soma-positivos -3 -2) 0

> (Exemplo 1.8) Uma bola é largada de uma altura h sobre uma superfície lisa, ficando a saltar

durante algum tempo. Supor que ao saltar, a bola toca a superfície sempre no mesmo ponto. A distância percorrida pela bola é a soma dos movimentos descendentes e ascendentes. Em cada salto, a bola sobe a uma altura que é calculada multiplicando h, altura do salto anterior, por um factor k, em que 0<k<1, designado por coeficiente de amortecimento. Vamos supor que o procedimento salto, com os parâmetros h e k, devolve a altura do salto da bola quando esta é largada da altura h.

Page 27: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 27

Escrever em Scheme o procedimento distancia-1, que toma os valores h e k, e devolve a distância percorrida pela bola desde o momento que é largada da altura h até ao final do primeiro salto, ou seja, a distância correspondente a uma descida seguida de uma subida. Este procedimento deverá utilizar o procedimento salto, como se vê no diagrama de fluxo de dados.

h distanciak

distancia-1

salto

h altura k

(define distancia-1 (lambda (h k) (+ h (salto h k)))) ; (define salto (lambda (h k) (* h k)))

> (distancia-1 2 .5) 3.0 > (distancia-1 3 .2) 3.6

> (Exercício 1.15) Tomando como referência o exemplo anterior, escrever agora o procedimento distancia-2, que toma os valores h e r, e devolve a distância percorrida pela bola desde o momento que é largada da altura h até ao final do segundo salto, ou seja, a bola desce, sobe, torna a descer e a subir.

> istancia-2 2 .5) (d4.5 > (distancia-2 3 .2) 4.32

> (Exercício 1.16) Um percurso rodoviário é composto por uma parte em piso horizontal, mas também apresenta uma subida e uma descida. De uma viatura é conhecido o consumo médio, aos 100 Km, quando se desloca em percurso horizontal.

Em relação a este consumo, a mesma viatura, em subida, gasta mais 30% e, em descida, menos 10%. Escrever em Scheme o procedimento consumo-total que tem como parâmetros consumo, horiz, sub e desc, que representam, respectivamente, o consumo médio da viatura em percurso horizontal, o

número de Km de percurso horizontal, o número de Km em subida e, finalmente, o número de Km em descida. Este procedimento deve devolver a quantidade em litros gasta pela viatura no percurso definido pelos parâmetros respectivos.

subida descida

> (Exercício 1.17)

Tomando como base o exercício anterior, pretende-se agora escrever o procedimento gasolina-suficiente que tem como parâmetros gas-no-tanque

Page 28: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 28

(que representa a quantidade de combustível que a viatura tem no tanque), e ainda os parâmetros do procedimento consumo-total. O procedimento pretendido deve responder, conforme o caso, com uma das seguintes mensagens:

• Nao e' suficiente. Faltam x litros. • E' suficiente. Sobram x litros. • Gasolina 'a justa.

Esboçar o diagrama de fluxo de dados que coloque em evidência a ligação entre os procedimentos utilizados.

> (Exemplo 1.9) Para este exercício vamos supor que a Terra é uma esfera perfeita, com um raio de 6378 Km. Sendo assim, o perímetro da Terra, quando se percorre o

Equador (latitude 0º) será de 2 x pi x 6378000 metros. Pretende-se conhecer o perímetro da Terra, percorrendo um paralelo ao Equador, identificado pela respectiva latitude (entre 0 e 90º, no Hemisfério Norte). Se para a latitude 0º o perímetro coincide com o comprimento do Equador, para a latitude 90º, que coincide com o pólo Norte, o perímetro será 0 metros.

66.50º Círculo Polar Árctico

0º Equador

Mas qual será o perímetro do trópico de Câncer, sabendo que se encontra à latitude 23.5º N? E o perímetro do Círculo Polar Árctico a 66.5º N? E o perímetro de outro paralelo qualquer?

Pretende-se definir o procedimento perimetro-paralelo que responde da seguinte forma: > (perimetro-paralelo 0) 40074155.889191404 metros > (perimetro-paralelo 66.5) 15979532.348780245 metros > (perimetro-paralelo 90) 2.4537532962986115e-009 metros > (perimetro-paralelo 89.5) 349708.5439343981 metros

Na resolução deste problema, como se pode ver pelo diagrama de fluxo de dados, principiámos pelo mais geral, com o procedimento perimetro-paralelo que trata apenas

da mensagem da resposta. Este procedimento recorre ao procedimento peri-paralelo que calcula o perímetro de um paralelo para uma certa latitude. latitude

perimetro-paralelo

latitude perimetro

peri-paralelo

latitude raio

raio-paralelo

Observando um pouco mais em profundidade, concluiremos que, por sua vez, peri-paralelo recorre ao procedimento raio-paralelo que devolve o raio do paralelo para uma latitude. A figura mostra como, a partir do raio da Terra e da latitude se pode calcular o raio do paralelo: Tendo em conta o triângulo rectângulo desenhado na figura,

Page 29: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 29

sabe-se que um cateto, raio, é igual à hipotenusa, neste caso coincidindo com o raio da terra, multiplicada pelo coseno do ângulo adjacente, lat.

(define raio-terra 6378000) ; raio da Terra em metros ; ; visualiza o resultado no formato indicado ; (define perimetro-paralelo (lambda (latitude) (display (peri-paralelo latitude)) (display " metros") (newline))) ; ; calcula o perímetro do paralelo cuja latitude é o argumento ; (define peri-paralelo (lambda (latitude) (* 2 pi (raio-paralelo latitude)))) ; ; calcula o raio do paralelo cuja latitude é o argumento ; (define raio-paralelo (lambda (lat) (* raio-terra (cos (degrees->radians lat))))) ; ; Procedimento que converte graus em radianos ; (define degrees->radians (lambda (ang) (/ (* pi ang) 180))) ; (define pi 3.141592653589793) ; valor de pi

> (Exercício 1.18) No contexto do exemplo anterior, supor que se colocava um arame de 40074155.889191404 metros e com ele se fazia um anel para colocar à volta da Terra, sobre o Equador. O anel ficava justo à Terra, portanto à distância zero, em todos os seus pontos. Imagine agora que cortava o anel e que lhe acrescentava um metro. O anel era novamente colocado à volta da Terra, no Equador, mas já não ficava completamente justo. Se o anel fosse colocado concêntrico com o Equador, a que distância ficaria o anel da Terra? Se uma experiência idêntica fosse feita num paralelo, muito junto ao Pólo Norte, com um arame igual ao seu perímetro, ao qual se acrescentaria também um metro. Neste caso, a que distância ficaria o anel da Terra?

O procedimento distancia-terra com dois parâmetros, um associado à latitude e outro ao comprimento de arame a acrescentar ao anel. Este procedimento determina a distância a que fica o anel da Terra, quando se lhe acrescenta aquele comprimento de arame.

raio-ext

raio-int Sugere-se a seguinte pista:

• Para a latitude dada, determinar o raio do respectivo paralelo, seja raio-int;

Page 30: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 30

• Para a latitude dada, determinar o perímetro do respectivo paralelo, conhecido raio-int. Acrescentar a este perímetro o comprimento dado;

• Determinar o raio correspondente ao perímetro aumentado, seja raio-ext; • Achar a diferença entre raio-ext e raio-int.

Escrever em Scheme o procedimento distancia-terra e experimentar, entre outras, as seguintes situações:

> (distancia-terra 0 1) ; acrescentar 1 metro no anel do Equador ??? > (distancia-terra 23.5 1) ; acrescentar 1 metro no anel ??? ; do Trópico de Câncer > (distancia-terra 66.5 1) ; acrescentar 1 metro no anel ??? ; do Círculo Polar Árctico > (distancia-terra 90 1) ; acrescentar 1 metro no anel do Pólo Norte ???

A análise dos resultados obtidos vai certamente conduzir a uma conclusão, que poderá ser considerada muito estranha...

> (Exercício 1.19) Para este exercício vai ser necessário relembrar, embora de uma forma um pouco simplificada, algumas fórmulas do movimento de projécteis no espaço. Um projéctil é lançado de um ponto (x0, y0), com a velocidade inicial v0 e o ângulo de lançamento ang. A velocidade inicial pode decompor-se em v0x e v0y. A velocidade v do projéctil, em cada momento, pode decompor-se em vx e vy. Despreza-se o atrito do ar quando o projéctil se move, supondo-se por isso que a velocidade vx é constante, enquanto que vy sofre apenas a influência permanente da gravidade (g = 9.75 m/s2). Assim, vy aponta para cima no início, vai diminuindo sucessivamente até atingir o valor zero. Isto acontece no ponto em que o projéctil atinge a altura máxima. A partir deste ponto, vy começa a apontar para baixo e a aumentar por influência da gravidade. As equações x e y definem a posição do projéctil, em função do ponto inicial, velocidade inicial, tempo e gravidade.

v0x = v0 . cos ang v0y = v0 . sin ang vx = v0x vy = v0y - g . t x = x0 + v0x . t y = y0 + v0y . t - 0.5 . g . t2

g = 9.75 m/s2

Page 31: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 31

No conjunto de exercícios que se seguem, considerar que o ponto de lançamento está na origem do sistema de eixos, ou seja, x0 = y0 = 0.

1- Escrever em Scheme o procedimento distancia-max, com os parâmetros vel-inicial e ang-inicial, correspondentes, respectivamente, à velocidade e ângulo iniciais do lançamento do projéctil. O procedimento devolve a distância máxima alcançada pelo projéctil. Pista sugerida:

⇒ Com a expressão y determinar t em que y = 0; ⇒ Determinar x, com a respectiva expressão, para o t

determinado.

2- Escrever em Scheme o procedimento altura-max, com os parâmetros, vel-inicial e ang-inicial, correspondentes, respectivamente, à velocidade e ângulo iniciais do lançamento do projéctil. O procedimento devolve a altura máxima alcançada pelo projéctil. Pista sugerida:

⇒ Com vy determinar t em que vy =0; ⇒ Determinar y, com a respectiva expressão, para o t

determinado.

3- Escrever em Scheme o procedimento posicao, com três parâmetros, vel-inicial, ang-inicial e tempo, correspondentes, respectivamente, à velocidade e ângulo iniciais do lançamento de um projéctil, e ao intervalo de tempo contado a partir do lançamento. O procedimento, através de mensagem apropriada, visualiza as coordenadas x e y da posição onde se encontra o projéctil, no final daquele intervalo de tempo. Pista sugerida:

⇒ Calcular vox e voy, através de v0 e ang; ⇒ Determinar x e y, para o t fornecido.

4- Com base nos procedimentos desenvolvidos, tentar algumas experiências:

⇒ Com várias chamadas de distancia-max e para uma certa velocidade inicial, tentar descobrir qual o ângulo que permite o lançamento mais longo.

⇒ Com várias chamadas de altura-max e para uma certa velocidade inicial, tentar descobrir qual o ângulo que permite o lançamento mais alto.

⇒ Com várias chamadas de posicao, mantendo fixos a velocidade e o ângulo iniciais, e fazendo variar o tempo, obter os dados necessários para desenhar em papel quadriculado a trajectória do projéctil.

Page 32: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 32

> sec1-8 Resumo

Neste capítulo fez-se uma introdução à linguagem Scheme, o que nos deu acesso ao conhecimento da linguagem necessário ao desenvolvimento de procedimentos e de pequenos programas.

Vimos que as expressões em Scheme utilizam uma notação pré-fixa, nas quais o operador antecede os operandos. Assim, por exemplo, para somar os números 23, 4 e 33, escrever-se-á (+ 23 4 33). Na chamada de um procedimento, seja primitivo ou composto pelo utilizador, é exigido o cálculo prévio dos operandos ou argumentos. Por exemplo, em (remainder (* num 5) 8), (* num 5) é calculado necessariamente antes de remainder e, por seu lado, o identificador num é calculado antes da multiplicação. A definição de identificadores pode concretizar-se com (define identificador expressão), que associa o valor de expressão a identificador. Os operadores aritméticos apresentados no capítulo foram: +, -, * e /. Podemos ainda acrescentar add1 e sub1, equivalentes a somar e a subtrair uma unidade. O procedimento random não faz parte da especificação do Scheme. No DrScheme, este procedimento é definido com um parâmetro n e a chamada (random n) gera um número aleatório entre 0 e n-1. Das chamadas de display não se espera um valor de retorno, contrariamente ao que acontece com a grande maioria dos procedimentos, mas apenas um efeito lateral de visualização de entidades no ecrã. Por exemplo, (display "Mensagem") visualiza "Mensagem" e (display (* 2 3)) visualiza o valor numérico 6. Com newline a visualização passa para o início da linha seguinte. Por outro lado, read permite a entrada de dados através do teclado. A definição de variáveis locais, para aumentar a legibilidade e o desempenho dos procedimentos, é possível com let. Dos procedimentos envolvendo cálculos trigonométricos distinguem-se: sin, asin, cos, acos, tan, atan, todos envolvendo ângulos em radianos. Estes procedimentos calculam, respectivamente, seno, arco-seno, coseno, arco-coseno, tangente e arco-tangente. A conversão radianos para graus e vice-versa é disponibilizada em certas implementações de Scheme, através dos procedimentos radians->degrees e degrees->radians. Nos exemplos e exercícios desenvolvidos com o DrScheme, optou-se por escrever aqueles procedimentos. Igualmente se optou por definir a constante pi como sendo igual a 3.141592653589793. As estruturas de selecção if e cond permitem a implementação de decisões sob condições. As condições simples podem ser especificadas com operadores de relação (>, >=, <, <=, =), e as condições compostas podem ser especificadas com os operadores lógicos (and, or, not). A condição composta (and (< num 10) (>= num 0)) é verdadeira se as duas condições simples forem verdadeiras, ou seja, se num for

Page 33: cap1 Introdução à linguagem Scheme - UFRGSinf.ufrgs.br/~rgoliveira/doku/data/media/inf05008/preguica_de... · valor, situação que foi oportunamente identificada e assinalada

Introdução à linguagem Scheme 33

menor que 10 e também maior ou igual que 0. As condições apresentam um valor booleano, que se assumirá verdadeiro, #t, ou falso, #f. Um procedimento que devolva um booleano é designada por predicado. Em Scheme, é habitual terminar o nome dos predicados com um ponto de interrogação. Seguem-se alguns predicados disponibilizados pelo Scheme: negative?, positive?, zero?, even?, odd?, boolean?, symbol?, procedure?, number?, integer?, real?. A construção begin permite agrupar várias expressões e este agrupamento poderá ocupar o lugar normalmente tomado por uma única expressão. Para além disto, as várias expressões agrupadas são calculadas em sequência da primeira até à última. No código que se segue, a construção de selecção if apresenta uma expressão-consequente com várias expressões agrupadas com um begin e a expressão-alternativa com apenas uma expressão. ... (if (positive? num) (begin ; expressão-consequente (display "Raiz quadrada de ") (display num) (display ": ") (display (sqrt num))) (display "Valor negativo")) ; expressão-alternativa ...

Embora a simplicidade dos exemplos apresentados no decorrer do capítulo não o exigisse, foi sendo introduzida a ideia de procurar identificar, perante um problema que se pretenda resolver, sub-problemas mais simples. Desta maneira, a escrita de um procedimento para resolver um problema surge como uma sequência de chamadas a procedimentos mais simples, correspondentes aos sub-problemas identificados. Trata-se de uma abordagem ao problema de-cima-para-baixo (top-down), assunto que será aprofundado em capítulos seguintes. A relação dos procedimentos entre si foi várias vezes posta em evidência através dos chamados diagramas de fluxos de dados. Do Anexo A, que resume os principais procedimentos do Scheme, recomenda-se o estudo, desde já, das secções correspondentes a Processamento lógico, Processamento numérico, Processamento trigonométrico, Estruturas de selecção, e Entrada/Saída.