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::dropFnFnMut, 和 FnOnce