2014-11-22 87 views
9

鑑於以下鏽程序:如何通過一個函數作爲參數拉斯特

fn call_twice<A>(val: A, f: fn(A) -> A) -> A { 
    f(f(val)) 
} 

fn main() { 
    fn double(x: int) -> int {x + x}; 
    println!("Res is {}", call_twice(10i, double)); 
    // println!("Res is {}", call_twice(10i, (x: int) -> int {x + x})); 
    //^this line will fail 
} 

我爲什麼可以通過double的功能,而不是內聯?沒有在某處定義函數,實現相同行爲的好方法是什麼?

回答

13

2016年4月1日更新:

鐵鏽1.0,代碼應該是這樣的:

fn call_twice<A, F>(val: A, mut f: F) -> A 
where F: FnMut(A) -> A { 
    let tmp = f(val); 
    f(tmp) 
} 

fn main() { 
    fn double(x: i32) -> i32 {x + x}; 
    println!("Res is {}", call_twice(10, double)); 
    println!("Res is {}", call_twice(10, |x| x + x)); 
} 

變化到封閉的參數是因爲封閉現在拆箱。

原文:

據我所知,你不能定義內聯函數這樣。

什麼你是一個封閉。以下作品:

fn call_twice<A>(val: A, f: |A| -> A) -> A { 
    let tmp = f(val); 
    f(tmp) 
} 

fn main() { 
    fn double(x: int) -> int {x + x}; 
    println!("Res is {}", call_twice(10i, double)); 
    println!("Res is {}", call_twice(10i, |x| x + x)); 
} 

這裏有幾點需要注意:

  1. 功能強迫工廠倒閉,但相反的是不正確的。

  2. 您需要的f(val)結果在臨時存儲由於借貸規則。短版本:您需要獨立訪問閉包來調用它,借用檢查程序不夠聰明,無法實現這兩個調用在原始位置是獨立的。

  3. 關閉正在被替換爲取消封閉關閉,所以這將在未來發生變化,但我們還沒有完成。

+0

感謝您的解釋。這個臨時變量有點奇怪,但我認爲這會在更穩定的版本中修復。 – 2014-11-23 09:21:24

+0

這似乎並不具有防鏽1.7的工作:https://play.rust-lang.org/?gist=ad35b80eeae1d1966944a66a75d0ad80&version=stable – 2016-03-31 14:48:09

+2

@SandeepDatta這個答案是在2014年;即使在Rust 1.0上,該代碼也會失效。我已經更新了它。 – 2016-04-01 01:18:13

相關問題