Scheme (recursão profunda)
Programação funcional
Recursão profunda
Até agora temos trabalhado com listas de átomos, usando recursão para processar seu conteúdo. Definimos como lista profunda uma lista que contém outras listas. Listas profundas podem ser pensadas como árvores. Exemplo:
(a ((b c)) (d (e (f))) g)
(a ((b c)) (d (e (f))) g)
|
----------------------------------------
| | | |
a ((b c)) (d (e (f))) g
| |
| ----------
| | |
(b c) d (e (f))
| |
------ --------
| | | |
b c e (f)
|
f
Para explorar a árvore completamente, é preciso usar recursão profunda. O função usa recursão profunda quando chama a si própria recursivamente no car e no cdr da lista.
Implementação de recursão profunda em Scheme
Para implementar funções com recursão profunda, devemos considerar as características da lista passada como parâmetro para a função. Considere a função (conta-prof x lista)
, que indica o número de ocorrências de x
na lista lista
, que pode ou não ser profunda.
Consideramos três casos:
- a lista é vazia (caso base): retorna 0.
- o primeiro elemento da lista é uma lista não-vazia: nesse caso, devemos contar o número de ocorrências de
x
no primeiro elemento dalista
(que é uma lista) e na cauda dalista
. O total de ocorrências vai ser a soma desses dois números. - o primeiro elemento da lista é um átomo: nesse caso, usamos uma lógica parecida com a usada na contagem de elementos em listas não-profundas:
- se o primeiro elemento é igual a
x
, retornamos 1 + número de ocorrências dex
na cauda dalista
. - se o primeiro elemento é diferente de
x
, retornamos o número de ocorrências dex
na cauda dalista
.
- se o primeiro elemento é igual a
IMPORTANTE!!!: Para checar se x
é uma lista não-vazia, use (pair? x)
(retorna t
somente se x
for uma lista não-vazia).
Exemplo: conta-prof
Implemente a função (conta-prof x lista)
, que indica o número de ocorrências de x
na lista lista
, que pode ou não ser profunda.
Exemplo: membro-prof
Implemente a função (membro-prof x lista)
, que indica se x
aparece na expressão lista
, que pode ou não ser profunda.
Dica
Note que as duas funções de recursão profunda são muito parecidas. O que muda de uma pra outra:
- o valor retornado no caso base (
0
vs.#f
) - a função usada para combinar os dois valores retornados pela chamada recursiva (
+
vs.or
)
Exemplo: subst
Crie uma função, (subst x y expr)
, que substitui as oorrências de x
por y
na expressão expr
, usando recursão profunda.
Antes de implementar, responda: que função você vai usar para combinar os resultados das chamadas recursivas?
Exemplo: flatten
Crie uma função, (flatten lista)
, que “achata” a lista, isto é, retorna uma lista de átomos com a mesma sequência de átomos da lista profunda lista
.