2013-10-12 76 views
4

我很難傳遞和評估閉包列表。大規模簡化,這個方案表現出同樣的錯誤的程序,我試着寫:傳遞和評估生鏽閉包

use std::vec::flat_map; 

#[main] 
fn main() { 
    let list:~[~fn()->~[~str]] = get_list(); 
    //let res:~[~str] = flat_map(list, |&f|{f()}); 
    let res:~[~str] = flat_map(list, apply); 
    println(res.to_str()); 
} 

fn apply<T>(f:&fn()->T) -> T { 
    f() 
} 

fn get_list() -> ~[~fn()->~[~str]] { 
    ~[ 
    ~||{~[~"foo"]}, 
    ~||{~[~"bar"]}, 
    ] 
} 

這基本上是試圖採取的返回列表的功能列表,並將其轉化爲運行結果的平面列表功能。我得到不過2個編譯器錯誤:

temp.rs:7:35: 7:40 error: mismatched types: expected `&fn<no-bounds>(&~fn:Send() -> ~[~str]) -> ~[<V3>]` but found `extern "Rust" fn(&fn<no-bounds>() -> <V4>) -> <V4>` (expected &-ptr but found fn) 
temp.rs:7 let res:~[~str] = flat_map(list, apply); 
              ^~~~~ 
temp.rs:16:2: 19:5 error: mismatched types: expected `~[~fn:Send() -> ~[~str]]` but found `~[~&fn<no-bounds>() -> ~[~str]]` (expected fn but found ~-ptr) 
temp.rs:16 ~[ 
temp.rs:17  ~||{~[~"foo"]}, 
temp.rs:18  ~||{~[~"bar"]}, 
temp.rs:19  ] 
error: aborting due to 2 previous errors 

首先,無論是功能apply也不是說我有註釋掉拉姆達讓我整個的函數列表映射。其次,在功能get_list()我無法生成可接受的向量。

回答

6

存在兩個問題:一個是Rust中的錯誤,另一個實際上是代碼問題。

  • 魯斯特的錯誤推論是帶密封蓋是(目前)可怕,就必須給他們明確的類型,當一個人想比&fn其他任何東西。 (這方面的一個申請是#2190
  • 在你的代碼中的錯誤是由於flat_map

    pub fn flat_map<T, U>(v: &[T], f: &fn(t: &T) -> ~[U]) -> ~[U] 
    

    類型的一點是它傳遞&T於封閉,從而,因爲我們有一個~[~fn() -> ~str],關閉收到&(~fn() -> ~str)。爲了召喚這樣一個野獸,我們需要對它進行解引用,這是|&f| f()所做的,但是以非法的方式。法律方法是|f| (*f)()

    不正確的方法會使f有型~fn() -> ~str這意味着f具有封閉的所有權(因爲~有析構函數,所以moves ownership時通過周圍),但一個無法把這種包含在一值的所有權借用指針(這將是無禮的)。合法的一方不會嘗試取得所有權,(*f)()在調用之前(有效)將~fn() -> ~str強制爲&fn() -> ~str。 (這是明確的,如果一個正確使用apply太:list.flat_map(|f| apply(*f)))

fn main() { 
    let list = get_list(); 
    let res = list.flat_map(|f| (*f)()); 
    println(res.to_str()); 
} 

fn get_list() -> ~[~fn() -> ~[~str]] { 
    let f1: ~fn() -> ~[~str] = || ~[~"foo"]; 
    let f2: ~fn() -> ~[~str] = || ~[~"bar"]; 

    ~[f1, f2] 
} 

(注意我刪除了不必要的類型註釋,以及所使用的flat_map method而不是功能,因爲這是Rust style)

+0

謝謝,這非常有用。你可能可以告訴我仍然在包裝類型系統的包裝:)。 –

+0

該錯誤被標記爲已修復,值得更新? – ideasman42