2014-10-10 24 views
6

如何迭代一系列閉包,然後依次調用每個閉包?從Rust中的數組調用閉包

用的功能,我發現我可以只遍歷數組過來,並取消引用所產生的價值做到這一點:

fn square(x: int) -> int { x * x } 

fn add_one(x: int) -> int { x + 1 } 

fn main() { 
    let funcs = [square, add_one]; 
    for func in funcs.iter() { 
     println!("{}", (*func)(5i)); 
    } 
} 

然而,當我試圖做同樣的封鎖,我得到一個錯誤:

fn main() { 
    let closures = [|x: int| x * x, |x| x + 1]; 
    for closure in closures.iter() { 
     println!("{}", (*closure)(10i)); 
    } 
} 

產地:

<anon>:4:24: 4:34 error: closure invocation in a `&` reference 
<anon>:4   println!("{}", (*closure)(10i)); 
           ^~~~~~~~~~ 
note: in expansion of format_args! 
<std macros>:2:23: 2:77 note: expansion site 
<std macros>:1:1: 3:2 note: in expansion of println! 
<anon>:4:9: 4:41 note: expansion site 
<anon>:4:24: 4:34 note: closures behind references must be called via `&mut` 
<anon>:4   println!("{}", (*closure)(10i)); 
           ^~~~~~~~~~ 
note: in expansion of format_args! 
<std macros>:2:23: 2:77 note: expansion site 
<std macros>:1:1: 3:2 note: in expansion of println! 
<anon>:4:9: 4:41 note: expansion site 

如果我嘗試聲明迭代瓦里能夠ref mut,它仍然不能正常工作:

fn main() { 
    let closures = [|x: int| x * x, |x| x + 1]; 
    for ref mut closure in closures.iter() { 
     println!("{}", (*closure)(10i)); 
    } 
} 

結果:

<anon>:4:24: 4:39 error: expected function, found `&|int| -> int` 
<anon>:4   println!("{}", (*closure)(10i)); 
           ^~~~~~~~~~~~~~~ 
note: in expansion of format_args! 
<std macros>:2:23: 2:77 note: expansion site 
<std macros>:1:1: 3:2 note: in expansion of println! 
<anon>:4:9: 4:41 note: expansion site 

如果我添加其他非關聯:

fn main() { 
    let closures = [|x: int| x * x, |x| x + 1]; 
    for ref mut closure in closures.iter() { 
     println!("{}", (**closure)(10i)); 
    } 
} 

我回到原來的錯誤:

<anon>:4:24: 4:35 error: closure invocation in a `&` reference 
<anon>:4   println!("{}", (**closure)(10i)); 
           ^~~~~~~~~~~ 
note: in expansion of format_args! 
<std macros>:2:23: 2:77 note: expansion site 
<std macros>:1:1: 3:2 note: in expansion of println! 
<anon>:4:9: 4:42 note: expansion site 
<anon>:4:24: 4:35 note: closures behind references must be called via `&mut` 
<anon>:4   println!("{}", (**closure)(10i)); 
           ^~~~~~~~~~~ 
note: in expansion of format_args! 
<std macros>:2:23: 2:77 note: expansion site 
<std macros>:1:1: 3:2 note: in expansion of println! 
<anon>:4:9: 4:42 note: expansion site 

我在這裏錯過了什麼?是否有文檔介紹這是如何工作的?

回答

7

矢量產量不變引用的.iter()方法,你需要可變的人打電話給關閉,因此,你應該使用.iter_mut()

fn main() { 
    let mut closures = [|x: int| x * x, |x| x + 1]; 
    for closure in closures.iter_mut() { 
     println!("{}", (*closure)(10i)); 
    } 
} 

----- 

100 
11 
+1

啊,謝謝。有沒有什麼辦法可以強制閉包是不可變的,所以它不需要通過可變引用來調用,作爲解決問題的另一種方法? – 2014-10-10 14:14:01

+0

嗯。使用'unboxed_closures'功能門嘗試使用'[|&:x:int |'來完成此操作x * x,|&:x:int | x + 1]',但得到了不可思議的錯誤「錯誤:不匹配的類型:預計\'關閉\',找到\'關閉\'(預期關閉,找到關閉)」。無論如何,你回答了我的原始問題,我會看看我是否可以找出未裝箱的關閉問題。 – 2014-10-10 14:28:55

+0

@BrianCampbell我也在研究這個。看起來像取消裝箱的關閉功能是有原因的。我認爲類型推斷仍然是越野車。 – Levans 2014-10-10 14:31:27