Rust作為輸入參數
作為輸入參數
大家已經注意到,Rust選擇無需注解在運行時捕捉變量。這在正常使用時很方便,但是編寫函數時,這種模糊性是不允許的。封閉的類型齊全,包括其捕獲類型必須注明。捕獲封閉使用被注釋為以下特征之一的方式:
-
Fn
: 通過引用以捕獲 (&T
) -
FnMut
: 通過可變引用需要捕獲 (&mut T
) -
FnOnce
: 通過值捕獲 (T
)
即使是注釋,這些都是非常靈活: FnOnce的一個參數指定封閉可以通過T或 &mut T 或 &T在將捕獲(如果此舉是可能的,任何類型的借還應該是可能的)。 反向並非如此:如果該參數為Fn,那麼什麼都降低是允許的。因此,規則是:
- 任何注釋的參數限製捕捉到自身
此外,Rust會優先捕捉,可變通過變量基礎變量限製最少的方式:
// A function which takes a closure as an argument and calls // it. The closure takes no input and returns nothing. fn apply(f: F) where F: FnOnce() { // ^ TODO: Try changing this to `Fn` or `FnMut`. f() } // A function which takes a closure and returns an `i32`. fn apply_to_3 (f: F) -> i32 where // The closure takes an `i32` and returns an `i32`. F: Fn(i32) -> i32 { f(3) } fn main() { let greeting = "hello"; // A non-copy type. let mut farewell = "goodbye".to_owned(); // Capture 2 variables: `greeting` by reference and // `farewell` by value. let diary = || { // `greeting` is by reference: requires `Fn`. println!("I said {}.", greeting); // Mutation forces `farewell` to be captured by // mutable reference. Now requires `FnMut`. farewell.push_str("!!!"); println!("Then I screamed {}.", farewell); println!("Now I can sleep. zzzzz"); // Manually calling drop forces `farewell` to // be captured by value. Now requires `FnOnce`. drop(farewell); }; // Call the function which applies the closure. apply(diary); let double = |x| 2 * x; println!("3 doubled: {}", apply_to_3(double)); }
也可以參考:
std::mem::drop, Fn, FnMut, 和 FnOnce