Fn, FnMut, FnOnce
Cechy domknięć
Fn, FnMut, FnOnce to bezpłatna lekcja Learn Rust Coding na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Learn Rust Coding, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.
Cechy domknięć
Każde domknięcie automatycznie implementuje jedną lub więcej z trzech cech, zależnie od sposobu używania przechwyconych wartości:
Fn— pożycza niezmiennie.FnMut— pożycza mutowalnie.FnOnce— przejmuje własność i można je wywołać raz.
fn main() {
let x = 5;
let show = || println!("x is {}", x); // implements Fn
show();
show();
}Fn: pożyczanie niezmienne
Domknięcie, które tylko odczytuje przechwycone wartości, implementuje Fn. Można je wywoływać wiele razy bez wprowadzania zmian.
fn main() {
let greeting = String::from("Hi");
let say = || println!("{}", greeting);
say();
say();
}FnMut: pożyczanie mutowalne
Domknięcie, które zmienia przechwyconą wartość, implementuje FnMut. Sama zmienna domknięcia musi być oznaczona jako mut, aby można było je wywołać.
fn main() {
let mut count = 0;
let mut increment = || {
count += 1;
println!("count {}", count);
};
increment();
increment();
}FnOnce: przejmowanie własności
Domknięcie, które przenosi przechwyconą wartość ze środowiska, implementuje FnOnce. Można je wywołać tylko raz.
fn main() {
let name = String::from("Ada");
let consume = move || {
let owned = name;
println!("consumed {}", owned);
};
consume();
}Hierarchia cech
Cechy tworzą hierarchię:
- Każde
Fnjest równieżFnMutiFnOnce. - Każde
FnMutjest równieżFnOnce.
Dlatego Fn jest najbardziej elastyczne, a FnOnce — najmniej.
fn main() {
let value = 42;
let read = || value; // Fn, so also FnMut and FnOnce
println!("{}", read());
}Przekazywanie Fn do funkcji
Funkcja może przyjmować domknięcie, określając wymaganą cechę. Należy użyć generyków z ograniczeniem cechy.
fn apply<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
f(x)
}
fn main() {
let double = |n| n * 2;
println!("{}", apply(double, 9));
}Przyjmowanie FnMut
Jeśli funkcja musi modyfikować przechwycony stan, należy wymagać FnMut i oznaczyć parametr jako 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
}Przyjmowanie FnOnce
Jeśli funkcja wywołuje domknięcie tylko raz i może pozwolić mu na zużycie wartości, należy wymagać 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);
}Słowo kluczowe move
Słowo kluczowe move wymusza przejęcie przez domknięcie własności przechwyconych zmiennych zamiast ich pożyczania.
Jest to niezbędne, gdy domknięcie musi istnieć dłużej niż zakres, w którym je utworzono, na przykład w wątkach.
fn main() {
let data = vec![1, 2, 3];
let printer = move || println!("{:?}", data);
printer();
}Jak Rust wybiera cechę
Nie wybierasz cechy ręcznie. Kompilator decyduje na podstawie treści domknięcia:
- Tylko odczytuje →
Fn - Modyfikuje →
FnMut - Przenosi przechwyconą wartość →
FnOnce
fn main() {
let mut log = Vec::new();
let mut record = |x: i32| log.push(x); // FnMut
record(1);
record(2);
println!("{:?}", log);
}Wybór właściwego ograniczenia
Zgodnie z ogólną zasadą:
- Przyjmuj
Fn, gdy wystarczy wywoływanie i odczytywanie. - Przyjmuj
FnMut, gdy domknięcie modyfikuje stan. - Przyjmuj
FnOnce, gdy wystarczy jedno wywołanie.
Wybierz najbardziej liberalne ograniczenie, które spełnia wymagania.
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));
}Szybkie sprawdzenie
Dopasuj zachowanie domknięcia do jego cechy.
Podsumowanie
Trzy cechy domknięć:
Fn— pożycza niezmiennie, można wywoływać wielokrotnie.FnMut— pożycza mutowalnie, może zmieniać stan.FnOnce— przejmuje własność, można wywołać raz.
Kompilator wyprowadza cechę, a move wymusza przejęcie własności przechwytywanych wartości.
fn main() {
let base = 5;
let adder = move |x: i32| x + base; // Fn, captures base by move
println!("{}", adder(10));
}Często zadawane pytania
Czy lekcja „Fn, FnMut, FnOnce” jest bezpłatna?
Tak — pełny tekst „Fn, FnMut, FnOnce” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Learn Rust Coding, przejdź na CoddyKit PRO. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.
Co nauczysz się w „Fn, FnMut, FnOnce”?
Cechy domknięć Ćwiczysz Learn Rust Coding z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Learn Rust Coding?
Nie wymagamy żadnego doświadczenia. Learn Rust Coding w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Fn, FnMut, FnOnce”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Learn Rust Coding?
Tak. Każda lekcja Learn Rust Coding zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Definiowanie funkcji
- Wyrażenia i instrukcje
- Domknięcia
- Fn, FnMut, FnOnce