Fn, FnMut, FnOnce
Características de closures
Fn, FnMut, FnOnce é uma aula grátis de Learn Rust Coding no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Learn Rust Coding, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Learn Rust Coding inclui 4 aulas no total.
As características dos fechamentos
Todo fechamento implementa automaticamente uma ou mais de três características, conforme a maneira como usa os valores capturados:
Fn— toma empréstimos imutáveis.FnMut— toma empréstimos mutáveis.FnOnce— assume a propriedade e pode ser chamado uma vez.
fn main() {
let x = 5;
let show = || println!("x is {}", x); // implements Fn
show();
show();
}Fn: empréstimo imutável
Um fechamento que apenas lê os valores capturados implementa Fn. Ele pode ser chamado muitas vezes sem alterar nada.
fn main() {
let greeting = String::from("Hi");
let say = || println!("{}", greeting);
say();
say();
}FnMut: empréstimo mutável
Um fechamento que altera um valor capturado implementa FnMut. A própria variável do fechamento precisa ser mut para que ele seja chamado.
fn main() {
let mut count = 0;
let mut increment = || {
count += 1;
println!("count {}", count);
};
increment();
increment();
}FnOnce: assume a propriedade
Um fechamento que move um valor capturado para fora do ambiente implementa FnOnce. Ele só pode ser chamado uma vez.
fn main() {
let name = String::from("Ada");
let consume = move || {
let owned = name;
println!("consumed {}", owned);
};
consume();
}A hierarquia das características
As características formam uma hierarquia:
- Todo
Fntambém éFnMuteFnOnce. - Todo
FnMuttambém éFnOnce.
Assim, Fn é o mais flexível e FnOnce, o menos flexível.
fn main() {
let value = 42;
let read = || value; // Fn, so also FnMut and FnOnce
println!("{}", read());
}Passando Fn para funções
Uma função pode aceitar um fechamento especificando de qual característica precisa. Use genéricos com uma restrição de característica.
fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
f(x)
}
fn main() {
let double = |n| n * 2;
println!("{}", apply(double, 9));
}Aceitando FnMut
Se sua função precisar alterar um estado capturado, exija FnMut e marque o parâmetro como mut.
fn call_twice<F: FnMut()>(mut f: F) {
f();
f();
}
fn main() {
let mut total = 0;
call_twice(|| total += 1);
// note: total is borrowed during the call
}Aceitando FnOnce
Quando uma função chama o fechamento apenas uma vez e pode permitir que ele consuma valores, exija FnOnce.
fn run_once<F: FnOnce() -> String>(f: F) {
let result = f();
println!("{}", result);
}
fn main() {
let s = String::from("done");
run_once(move || s);
}A palavra-chave move
A palavra-chave move força um fechamento a assumir a propriedade das variáveis capturadas em vez de tomar empréstimos delas.
Isso é essencial quando um fechamento precisa sobreviver ao escopo em que foi criado, como em threads.
fn main() {
let data = vec![1, 2, 3];
let printer = move || println!("{:?}", data);
printer();
}Como o Rust escolhe a característica
Você não escolhe a característica manualmente. O compilador decide com base no corpo do fechamento:
- Apenas lê →
Fn - Altera →
FnMut - Move um valor capturado para fora →
FnOnce
fn main() {
let mut log = Vec::new();
let mut record = |x: i32| log.push(x); // FnMut
record(1);
record(2);
println!("{:?}", log);
}Escolhendo a restrição correta
Como regra:
- Aceite
Fnquando precisar apenas chamar e ler. - Aceite
FnMutquando o fechamento alterar o estado. - Aceite
FnOncequando uma única chamada for suficiente.
Escolha a restrição mais permissiva que seja adequada.
fn each<F: Fn(i32)>(items: &[i32], f: F) {
for &i in items {
f(i);
}
}
fn main() {
each(&[1, 2, 3], |n| println!("got {}", n));
}Verificação rápida
Associe o comportamento de uma closure à sua trait.
Recapitulação
As três traits de closure:
Fn— faz empréstimo imutável e pode ser chamada repetidamente.FnMut— faz empréstimo mutável e pode alterar o estado.FnOnce— assume a propriedade e pode ser chamada uma vez.
O compilador infere a trait; move força a captura por propriedade.
fn main() {
let base = 5;
let adder = move |x: i32| x + base; // Fn, captures base by move
println!("{}", adder(10));
}Perguntas Frequentes
A aula “Fn, FnMut, FnOnce” é grátis?
Sim — o texto completo de “Fn, FnMut, FnOnce” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Learn Rust Coding, atualize para CoddyKit PRO. O curso de Learn Rust Coding inclui 4 aulas no total.
O que vou aprender em “Fn, FnMut, FnOnce”?
Características de closures Você pratica Learn Rust Coding com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Learn Rust Coding?
Nenhuma experiência prévia é necessária. Learn Rust Coding no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Fn, FnMut, FnOnce”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Learn Rust Coding?
Sim. Cada aula de Learn Rust Coding inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Definição de funções
- Expressões e instruções
- Closures
- Fn, FnMut, FnOnce