Na programação funcional a função desejada é definida recorrendo à eventual definição de outras funções por abstracção funcional e à aplicação dessas funções e de outras funções predefinidas, eventualmente sobre listas ou mesmo outras funções.
Ao programarmos funcionalmente não utilizaremos a composição sequencial, comandos iterativos While e a memorização de valores em variáveis através de atribuições. As funções são utilizadas como argumento de outras funções (funcionais ou operadores). Para o conseguirmos recorremos aos funcionais Apply e Map.
Nesta secção optamos por nos referirmos em primeiro lugar ao Mathematica uma vez que consideramos que este apresenta melhores argumentos para abordar a programação funcional.
Mathematica:
O funcional Apply substitui a cabeça da expressão apresentada no segundo argumento pela função que consta no primeiro. Esta substituição é feita desde que a expressão seja não atómica.
Vejamos um exemplo da aplicação do funcional Apply.
Recorde-se que a lista {1,2,3,4} é representada em Mathematica por
List[1,2,3,4].
FullForm
@8
1, 2, 3, 4<D
List
@
1, 2, 3, 4D
Ao pretender obter a soma dos elementos que compõem a lista bastar-nos-ia substituir a cabeça List por Plus. Conseguimos fazê-lo facilmente aplicando o funcional
Apply.
Apply
@
Plus,8
1, 2, 3, 4<D
10
Ao pretender obter a definição de uma função que nos dê o factorial de um dado número inteiro não negativo teremos de utilizar um raciocínio semelhante ao anterior utilizando a multiplicação que em Mathematica se designa por Times.
Para calcular n! temos de construir uma lista com os números 1, 2, 3, ..., n. Ora podemos consegui-la utilizando a função Table.
Table
@
i,8
i, 4<D
8
1, 2, 3, 4<
Assim somos levados à seguinte definição de fact.
fact=Function
@
n, Apply@
Times, Table@
i,8
i, n<DDD
;fact
@
0D
fact
@
5D
120
Quanto ao funcional Map este faz com que uma dada função seja aplicada a todos os elementos de uma lista.
Map
@
g,8
3, 5, 11<D
8
g@
3D
, g@
5D
, g@
11D<
Posto isto podemos passar à definição funcional da função pertence.
A ideia subjacente a esta função é percorrer a lista e comparar um a um todos os elementos da lista com o elemento que queremos encontrar. Temos portanto de definir uma função que compare cada elemento da lista com o elemento que queremos pesquisar.
Depois obteremos uma lista composta por elementos que serão True ou False. A função pertence deverá dar True nos casos em que existe pelo menos um True na lista anterior. Daqui surge como imediata a aplicação da função Or.
Assim a definição para a função pertence poderá ser a seguinte.
pertence= Function
@8
w, x<
,Apply
@
Or, Map@
Function@
y, yŠ xD
, wDDD
; pertence@8
1, 2, 3, 4<
, 3D
True pertence@8
1, 2, 3, 4<
, 0D
False pertence@8
1, 2, 3, 4<
, 4D
True pertence@8
1, 2, 3, 4<
, 7D
FalseDerive:
No Derive podemos utilizar a função MAP_LIST para distribuir a aplicação de uma função pelos elementos de listas e conjuntos.
Nos casos em que u é uma expressão envolvendo a variável x e c é um conjunto ou uma lista, MAP_LIST(u,x,c) avalia u(x) quando x é igual a cada um dos elementos de c e retorna um conjunto ou uma lista.
Podemos ainda aplicar a função MAP_LIST com mais do que três argumentos. Nesses casos é possível indicar onde deve começar a aplicação da função, onde deve terminar e qual o tamanho dos passos a dar.
PRODUCT. Tendo em conta esse facto podemos definir a função factorial como fact(n) :=PRODUCT(x, x, 1, n). Carregando em ENTER a nossa função fica registada
na nossa zona de trabalho como se segue.
Na definição da função pertence já sentimos a necessidade de utilizar a função
MAP_LIST à qual já fizemos referência. Neste caso particular a função anterior tem
por objectivo verificar se alguma das entradas da lista coincide com o elemento introduzido. Na definição da função pertence criamos uma função auxiliar de nome
ou_lista que permite o cálculo da disjunção dos elementos de uma lista composta pelas
constantes booleanas true ou false. Tal foi feito mediante a utilização de uma expressão condicional em que nos casos em que o elemento da lista era true era transformado em
1 e 0 nos restantes casos. Depois, somando os valores, e tendo em conta que a disjunção
de condições é verdadeira desde que exista pelo menos uma das condições que seja verdadeira, bastou impor que caso a soma fosse maior que 0 a função ou_lista desse
true. A definição para a função encontrada foi a seguinte: ou_lista(w) := IF( ΣΣΣΣ ( IF (y, 1, 0), y, w) > 0, true, false).
Para concluirmos a definição da nossa função temos de garantir que o argumento que é fornecido à função anterior lá chega nas condições pretendidas. Conseguimos isso pela comparação de cada entrada da lista original com o elemento do qual pretendemos saber se está ou não na lista para o que utilizamos o funcional MAP_LIST.
Maple:
Para conseguir definir funcionalmente a função factorial sentimos necessidade de definir localmente uma função a que chamamos sequencia cuja finalidade é a de simplesmente nos gerar o conjunto vazio quando o argumento da nossa função for zero. Isto fica a dever-se ao facto de seq( j, j =1 .. 0) não ser avaliado.
Caso não nos interessasse o caso do factorial de zero a nossa definição não necessitaria da função sequencia.
Vejamos que realmente nestas condições a função está de acordo com o que pretendíamos.
Para conseguir definir funcionalmente a função pertence seguimos aqui um raciocínio semelhante ao utilizado no Derive. Tal como lá, utilizamos uma função f que permite a comparação de cada elemento da lista com aquele que pretendemos saber se faz parte desta. Ao invocarmos a função pertence(w,x) onde w é a lista e x é o elemento, caso a função f encontre em w algum elemento que coincida com x este é transformado em 1 e nos restantes casos é alterado para 0. Posteriormente esses uns e zeros são adicionados permitindo que se obtenha true nos casos em que existia um (ou mais) elemento(s) iguais a x. Este é um método muito parecido com aquele que usamos para o Derive.