位置:首頁 > 高級語言 > Rust教學 > Rust作為輸入參數

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