Mapear uma lista de funções para uma lista
-
11-12-2019 - |
Pergunta
Este é o dever de casa, então não quero a resposta.Só preciso de um empurrão na direção certa.Sou obrigado a mapear várias funções em uma lista.Por exemplo:
(map-multi (list plus-one square) '(4 5 6)) => (25 36 49)
Consigo fazer com que ele mapeie a primeira função para os elementos da lista, porém fico muito perdido depois disso.Além disso, por ser introdutório, estou limitado às funções introdutórias (const
, append
, car
, cdr
, member
, etc.)
(define (map-multi f l)
(cond
((null? l)
l)
(else (cons ((car f) (car l))
(map-multi f (cdr l))))))
Solução
Você precisa compor as funções que você recebe no f
parâmetro.Para simplificar, digamos que existam apenas duas funções na lista - então você precisa aplicar a primeira função ao elemento atual na lista de números e depois aplicar a segunda função ao resultado disso.Se você puder usar o compose
procedimento, vá em frente e altere esta linha em seu código:
((car f) (car l)) ; you're applying only the 1st function! what about the 2nd?
...com este:
((compose (cadr f) (car f)) (car l)) ; now we're applying both functions
Se você não pode usar compose
, e substitua a mesma linha por esta:
((cadr f) ((car f) (car l))) ; now we're applying both functions
Agora, se o problema for mais geral e você precisar mapear uma lista de funções com mais de dois elementos e, mais uma vez, substitua a mesma linha em seu código por isto:
((compose-multi f) (car l))
E implemente uma função auxiliar que compõe e retorna todas as funções da lista, por meio de chamadas sucessivas para compose
.Este é deixado como um exercício para você, já que é um dever de casa - mas se você entender como o código acima funciona para apenas duas funções, deve ser fácil estender o resultado para uma lista de múltiplas funções:
(define (compose-multi flist) ; procedure for composing a list of functions
(if (null? flist) ; if the list is empty then
<???> ; return the identity function
(<???> (compose-multi <???>) ; else compose the result of recursive call
<???>))) ; with the current element in the list
Observe que a função identidade é necessária para tratar o caso em que não há elementos na lista de funções;é muito simples de definir, apenas retorna o mesmo valor que foi passado como parâmetro.
Também esteja ciente de que compose-multi
retorna um função, o resultado da composição de todas as funções da lista - compose
faz isso para você, mas se você não tiver permissão para usá-lo, lembre-se do seguinte:
(compose x y)
...é equivalente a isto:
(lambda (n) (x (y n)))
Outras dicas
Pode ser mais fácil escrever isso como duas funções.Pega-se uma lista de funções e uma única entrada e aplica-se todas as funções da lista em série.A saída de uma aplicação de função será a entrada para a próxima;quando você ficar sem funções, estará pronto.
A outra função simplesmente mapeará esta função auxiliar em uma lista de entradas.
Aqui está uma maneira alternativa de definir multi-map
que em vez de composição usa a operação chamada fold
.Como você só pode usar funções introdutórias, esta não é realmente a resposta para sua tarefa.Mas será, se você escrever sua própria definição de fold
(não é muito longo!)
(define (multi-map operations input)
(fold map input operations))
> (multi-map (list 1+ square)
'(4 10 8))
$2 = (25 121 81)
> (multi-map (list 1+ square 1+)
'(4 10 8))
$3 = (26 122 82)
Para se aquecer, comece com um problema mais simples.Em seguida, generalize a solução.
Como você escreveria esta função?
(define (map-single fs x)
...)
> (map-single (list double add1) 3)
7
Isso requer uma lista, fs
, de valores de função como argumento e um número, x
, e calculou o valor da aplicação das (composição de) funções em fs
para x
?