2013-06-05 2 views
21

이것은 매우 간단한 예이지만, 어떻게 비슷한 할 것 :녹에서 재귀 폐쇄가 가능합니까?

let fact = |x: u32| { 
    match x { 
     0 => 1, 
     _ => x * fact(x - 1), 
    } 
}; 

나는이 구체적인 예는 쉽게 반복하여 수행 할 수 있다는 것을 알고 있지만, 재귀을 할 수 있는지 궁금 해요 (나무를 횡단하는 것과 같이) 더 복잡한 일이나 내 자신의 스택을 대신 사용해야 할 필요가있는 경우에는 녹의 기능을 사용하십시오.

+1

Niko Matsakis는 잠재적 인 가능성에 대해 [멋진 게시물] (http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/)을 작성했습니다.) 클로저에서 재귀를 사용하고 왜 이것이 확실히 제거 될 것인가 (아직'들어오는 '경우). 물론 자신을 호출하는 함수를 항상 정의 할 수 있지만 외부 변수는 포착하지 않습니다. –

답변

20

몇 가지 방법이 있습니다.

구조체에 클로저를 넣고이 구조체를 클로저에 전달할 수 있습니다. 당신은 함수에 구조체를 인라인으로 정의 할 수 있습니다

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)); 
} 

을이 fact 아직 폐쇄 내부에 정의되어 있지 않은 것을 무한한 종류 (인수로 자신을 취하는 함수) 문제를 가지고있는 문제를 해결 도착 사람이 let fact = |x| {...}을 쓸 때 그 사람이 거기를 참조 할 수는 없습니다.

녹청 1.17에서 작동하지만 the blog post The Case of the Recurring Closure에 설명 된 것처럼 일부 경우 위험하기 때문에 나중에 불법화 될 수 있습니다. 그것은 돌연변이가 없기 때문에 여기서 완전히 안전합니다. 당신은 아무것도를 캡처 할 필요가없는 경우

fn main() { 
    fn fact(x: u32) -> u32 { if x == 0 {1} else {x * fact(x - 1)} } 

    println!("{}", fact(5)); 
} 

이 잘 작동 :


또 다른 옵션은 또한 기능에 인라인으로 정의 될 수 fn 항목으로 재귀 함수를 작성하는 것입니다 환경으로부터.


또 하나의 옵션은 fn 항목 솔루션을 사용하지만 명시 적으로 원하는 인수/환경을 전달하는 것입니다.

이러한 모든 작업은 녹 1.17과 호환되며 버전 0.6 이후로 작업했을 가능성이 큽니다. fn은 내부에 정의 된 fn 내에서만 액세스 할 수 있다는 점을 제외하고는 fn 내부에 정의 된 것과 다르지 않습니다.

관련 문제