Desafio Rust
Processador de números com closures
Enunciado
Implemente uma função processar que recebe um vetor de inteiros e duas closures: uma para filtrar (retorna bool) e outra para transformar (retorna i32). A função deve retornar um novo vetor com os elementos filtrados e transformados. Use move para capturar um multiplicador externo na closure de transformação.
Requisitos
- A função
processardeve aceitarF: Fn(i32) -> booleG: Fn(i32) -> i32. - A closure de filtro deve selecionar números pares.
- A closure de transformação deve multiplicar por um fator capturado com
move. - O programa deve imprimir o vetor resultante.
Código inicial
fn processar<F, G>(v: Vec<i32>, filtro: F, transformar: G) -> Vec<i32>
where
F: Fn(i32) -> bool,
G: Fn(i32) -> i32,
{
// Complete aqui: filtre e transforme
vec![]
}
fn main() {
let numeros = vec![1, 2, 3, 4, 5, 6];
let fator = 10;
// Complete aqui: defina as closures e chame processar
}
Saída esperada
[20, 40, 60]
Ver dica
Use v.into_iter().filter(|&x| filtro(x)).map(|x| transformar(x)).collect(). A closure de transformação pode ser move |x| x * fator.
Mostrar solução
fn processar<F, G>(v: Vec<i32>, filtro: F, transformar: G) -> Vec<i32>
where
F: Fn(i32) -> bool,
G: Fn(i32) -> i32,
{
v.into_iter()
.filter(|&x| filtro(x))
.map(|x| transformar(x))
.collect()
}
fn main() {
let numeros = vec![1, 2, 3, 4, 5, 6];
let fator = 10;
// Closure de filtro: mantém apenas pares
let eh_par = |x| x % 2 == 0;
// Closure de transformação: move fator para dentro
let multiplicar = move |x| x * fator;
let resultado = processar(numeros, eh_par, multiplicar);
println!("{:?}", resultado);
}
Passo a passo
- Definimos
processarcom dois parâmetros genéricosFeG, ambos closures. - A função usa
v.into_iter()para consumir o vetor e iterar por valor. .filter(|&x| filtro(x))aplica a closure de filtro, mantendo apenas elementos que retornamtrue..map(|x| transformar(x))aplica a closure de transformação a cada elemento restante..collect()coleta os resultados em um novoVec<i32>.- Em
main, criamoseh_parque verifica se um número é par. - Criamos
multiplicarcommove, capturandofatorpor valor. - Chamamos
processare imprimimos o vetor resultante.
Por que funciona
A função processar aceita closures que implementam Fn, pois apenas as chama sem modificar o ambiente. A closure eh_par captura nada e é Fn. A closure multiplicar usa move para capturar fator por valor, tornando-se Fn também (pois não modifica fator). O uso de into_iter permite consumir o vetor original, evitando cópias desnecessárias.
Erros comuns
- Esquecer o
movena closure de transformação:fatorseria emprestado, mas comoprocessarpode chamar a closure várias vezes, o empréstimo imutável também funcionaria. No entanto, sefatorfosse mutável ou se a closure precisasse de ownership,moveé necessário. - Usar
iter()em vez deinto_iter():iter()empresta os elementos, masfilteremapesperam valores; seria necessário desreferenciar.into_iter()simplifica. - Não declarar
filtroetransformarcomomutna assinatura: como sãoFn, não precisam ser mutáveis, então está correto.
Outra forma de resolver
Poderia usar v.into_iter().filter(|x| filtro(*x)).map(transformar).collect(). A diferença é que filter recebe &i32, então precisamos desreferenciar. A versão com |&x| é mais idiomática.
Saída esperada
[20, 40, 60]