2016-01-18 73 views
3

我可以做這樣的事情:如何用閉包定義相互遞歸?

fn func() -> (Vec<i32>, Vec<i32>) { 
    let mut u = vec![0;5]; 
    let mut v = vec![0;5]; 

    fn foo(u: &mut [i32], v: &mut [i32], i: usize, j: usize) { 
     for k in i+1..u.len() { 
      u[k] += 1; 
      bar(u, v, k, j); 
     } 
    } 
    fn bar(u: &mut [i32], v: &mut [i32], i: usize, j: usize) { 
     for k in j+1..v.len() { 
      v[k] += 1; 
      foo(u, v, i, k); 
     } 
    } 
    foo(&mut u, &mut v, 0, 0); 
    (u,v) 
} 

fn main() { 
    let (u,v) = func(); 
    println!("{:?}", u); 
    println!("{:?}", v); 
} 

,但我更願意做這樣的事情:

fn func() -> (Vec<i32>, Vec<i32>) { 
    let mut u = vec![0;5]; 
    let mut v = vec![0;5]; 

    let foo = |i, j| { 
     for k in i+1..u.len() { 
      u[k] += 1; 
      bar(k, j); 
     } 
    }; 
    let bar = |i, j| { 
     for k in j+1..v.len() { 
      v[k] += 1; 
      foo(i, k); 
     } 
    }; 
    foo(0, 0); 
    (u,v) 
} 

fn main() { 
    let (u,v) = func(); 
    println!("{:?}", u); 
    println!("{:?}", v); 
} 

第二個例子不與錯誤編譯:無法解析名稱bar。 在我的任務中,我可以通過一次遞歸來完成,但看起來不太清楚。 有沒有人有任何其他建議?

+0

也許這會更好,如果你在問題標題中指出,問題是互相遞歸? –

+0

謝謝,我只是不知道它是如何被稱爲 – vessd

+1

我很好奇,所以我搜索並找到了這個[關於正常單個遞歸的問題關閉](https://stackoverflow.com/questions/16946888/recursive-closure-in -鏽)。這也不直接支持,雖然這[回答](https://stackoverflow.com/questions/16946888/recursive-closure-in-rust/16953239#16953239)指出了一種方法來通過傳遞函數作爲參數自己。 –

回答

2

我有一個相互遞歸閉包的解決方案,但它不適用於多個可變借項,所以我無法將其擴展到您的示例。

有一種方法可以使用類似於this answer單遞歸的方法來定義相互遞歸閉包。你可以把閉包放在一個結構體中,每個結構體都可以借用該結構體作爲額外的參數。

fn func(n: u32) -> bool { 
    struct EvenOdd<'a> { 
     even: &'a Fn(u32, &EvenOdd<'a>) -> bool, 
     odd: &'a Fn(u32, &EvenOdd<'a>) -> bool 
    } 
    let evenodd = EvenOdd { 
     even: &|n, evenodd| { 
      if n == 0 { 
       true 
      } else { 
       (evenodd.odd)(n - 1, evenodd) 
      } 
     }, 
     odd: &|n, evenodd| { 
      if n == 0 { 
       false 
      } else { 
       (evenodd.even)(n - 1, evenodd) 
      } 
     } 
    }; 
    (evenodd.even)(n, &evenodd) 
} 

fn main() { 
    println!("{}", func(5)); 
    println!("{}", func(6)); 
} 
+0

嗯,這是我的問題的答案,但不幸的是不是我的解決方案。 – vessd

+0

是的。如果你作爲額外的參數傳遞了可變借款,它可能對你有用,但是你也可以使用本地'fn's,這是你的第一個解決方案。 –