Istnieje kilka sposobów, aby to zrobić.
Możesz umieścić zamknięcia w strukturze i przekazać tę strukturę do zamknięcia. Można nawet określić elemencie inline w funkcji:
fn main() {
struct Fact<'s> { f: &'s Fn(&Fact, u32) -> u32 }
let fact = Fact {
f: &|fact, x| if x == 0 {1} else {x * (fact.f)(fact, x - 1)}
};
println!("{}", (fact.f)(&fact, 5));
}
ten omija problem mający typu (nieskończoną funkcję, która zaczyna się jako argument) i problemu fact
nie została jeszcze zdefiniowana wewnątrz zamknięcia samemu, gdy pisze się let fact = |x| {...}
i dlatego nie można tam go odnieść.
Ta funkcja działa w wersji 1.17, ale w przyszłości może stać się nielegalna, ponieważ w niektórych przypadkach jest niebezpieczna, zgodnie z informacjami podanymi w the blog post The Case of the Recurring Closure. Jest tu całkowicie bezpieczny, ponieważ nie ma mutacji.
Inną opcją jest po prostu napisz rekurencyjną funkcję jako fn
elementu, który może być także zdefiniowane w funkcji inline:
fn main() {
fn fact(x: u32) -> u32 { if x == 0 {1} else {x * fact(x - 1)} }
println!("{}", fact(5));
}
Działa to dobrze, jeśli nie muszą przechwycić niczego ze środowiska.
Jeszcze jedna opcja to użycie rozwiązania fn
pozycji, ale wyraźnie przekazać args/Środowisko chcesz.
fn main() {
struct FactEnv { base_case: u32 }
fn fact(env: &FactEnv, x: u32) -> u32 {
if x == 0 {env.base_case} else {x * fact(env, x - 1)}
}
let env = FactEnv { base_case: 1 };
println!("{}", fact(&env, 5));
}
Wszystkie te elementy działają z rdzeniem 1.17 i prawdopodobnie działały od wersji 0.6. Zdefiniowane wewnątrz fn
s nie różnią się od zdefiniowanych na najwyższym poziomie, z wyjątkiem tego, że są dostępne tylko w obrębie fn
, które są zdefiniowane w środku.
Niko Matsakis napisał [wspaniały post] (http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/) o tym, jak możesz potencjalnie (ab) używaj rekursji w zamknięciach już teraz i dlaczego to na pewno zostanie usunięte (jeśli nie jest jeszcze w 'przychodzącym'). Oczywiście zawsze możesz zdefiniować funkcję, która wywołuje samą siebie, ale nie przechwyci zmiennych zewnętrznych. –