Bunu yapmanın birkaç yolu vardır.
Bir yapıya kapaklar koyabilir ve bu yapıyı kapamaya geçirebilirsiniz. Hatta bir işlevde yapılar satır içi tanımlayabilirsiniz:
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));
}
Bu fact
henüz kapanması içine tanımlı olmadığı sonsuz bir türünü (bağımsız değişken olarak kendini alır bir işlevi) ve sorunu olmasının sorunu alır Biri let fact = |x| {...}
yazdığında ve oraya bir tane atıfta bulunamaz.
Bu Rust 1,17 çalışır, ancak bazı durumlarda tehlikeli beri the blog post The Case of the Recurring Closure özetlendiği gibi muhtemelen gelecekte yasadışı yapılabilir. Burada hiçbir mutasyon olmadığı için burada tamamen güvenli. Bir şeye yakalamak için gerekmiyorsa
fn main() {
fn fact(x: u32) -> u32 { if x == 0 {1} else {x * fact(x - 1)} }
println!("{}", fact(5));
}
Bu çalışıyor:
Bir başka seçenek sadece, aynı zamanda bir fonksiyonu inline tanımlanabilir bir fn
öğe gibi bir özyinelemeli fonksiyon yazmaktır çevreden
Bir seçenek daha fn
madde çözümü kullanabilirsiniz ancak açıkça istediğiniz args/çevreyi geçmektir.
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));
}
Bunların hepsi Rust 1.17 ile çalışır ve muhtemelen sürüm 0.6'dan beri çalışmışlardır. fn
'un fn
s içinde tanımlanmış olması, üst düzeyde tanımlanmış olanlardan farklı değildir, sadece içeride tanımlanmış oldukları fn
içinde erişilebilir olmaları dışında.
Niko Matsakis'in nasıl potansiyel can hakkında [harika yazı] (http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/) (ab yazdı) şu anda kapanışlarda özyinelemeyi ve bunun neden en çok niçin kaldırılacağını (eğer zaten 'gelen' değilse). Tabii ki, her zaman kendini çağıran bir işlevi tanımlayabilirsiniz, ancak dış değişkenleri yakalamaz. –