Seguinte: Especialização Acima: Funções Anterior: Depuração de Funções
Índice remissivo

Funções de Ordem Superior

Vimos que as funções permitem-nos dar um nome a um conjunto de operações e tratá-lo como um todo. Muitas vezes, porém, há um padrão que se repete, variando apenas uma ou outra operação. Por exemplo, consideremos uma função que soma os quadrados de todos os inteiros entre a e b, tex2html_wrap_inline3318 .

(defun soma-quadrados (a b)
  (if (> a b)
    0
    (+ (quadrado a) (soma-quadrados (1+ a) b))))

> (soma-quadrados 1 4) 30

Consideremos agora uma outra função que soma as raizes quadradas de todos os inteiros entre a e b, tex2html_wrap_inline3324 .

(defun soma-raizes (a b)
  (if (> a b)
    0
    (+ (sqrt a) (soma-raizes (1+ a) b))))

> (soma-raizes 1 4) 6.146264369941973

Em ambas as funções existe uma soma de expressões matemáticas entre dois limites, i.e., existe um somatório tex2html_wrap_inline3326 . O somatório é uma abstracção matemática para uma soma de números. Dentro do somatório é possível colocar qualquer operação matemática relativa ao índice do somatório. Esse índice varia desde o limite inferior até ao limite superior.

Para que se possa definir o processo do somatório na nossa linguagem de programação ela deve ser capaz de fazer abstração sobre as próprias operações a realizar, e deve poder usá-las como se de parâmetros do processo se tratasse. O padrão a executar seria qualquer coisa do estilo:

(defun soma-??? (a b)
  (if (> a b)
    0
    (+ (aplica-??? a) (soma-??? (1+ a) b))))

O símbolo ??? representa a operação a realizar dentro do somatório, e que pretendemos transformar num parâmetro.

Em Lisp, para se aplicar uma função que é o valor de um argumento, usa-se a função funcall, que recebe essa função e os seus parâmetros actuais. Para se indicar que pretendemos a função associada a um determinado símbolo, usa-se a forma especial function.

> (function 1+)
#
> (funcall (function 1+) 9)
10
> (defun teste (f x y) (funcall f x y))
teste
> (teste (function +) 1 2)
3

Deste modo já podemos escrever a implementação do nosso somatório:

(defun somatorio (func a b)
  (if (> a b)
    0
    (+ (funcall func a) (somatorio func (1+ a) b))))

Podemos testar a função para o exemplo anterior.

> (somatorio (function quadrado) 1 4)
30

Como se vê, a função somatorio representa a abstracção associada ao somatório matemático. Para isso, ela recebe uma função como argumento e aplica-a aos sucessivos inteiros incluídos no somatório.

As funções que recebem e manipulam outras funções são designadas funções de ordem superior.

Exercício 19

Repare-se que, tal como a função somatório, podemos escrever a abstracção correspondente ao produtório (também designado piatório) tex2html_wrap_inline3328 . Esta abstracção corresponde ao produto dos valores de uma determinada expressão para todos os inteiros de um intervalo. Escreva uma função Lisp que a implemente.

Resposta

Exercício 20

Escreva a função factorial usando o produtório.

Resposta

Exercício 21

Quer o somatório, quer o produtório podem ser vistos como casos especiais de uma outra abstracção ainda mais genérica, designada acumulatório. Nesta abstracção, quer a operação de combinação dos elementos, quer a função a aplicar a cada um, quer o valor inicial, quer o limite inferior, quer a passagem para o elemento seguinte (designado o sucessor), quer o limite superior são parâmetros. Defina esta função. Defina o somatório e o produtório em termos de acumulatório.

Resposta


Seguinte: Especialização Acima: Funções Anterior: Depuração de Funções
Índice remissivo

Copyright António Leitão, 1995