簡體   English   中英

Rust 高階函數的壽命

[英]Rust Lifetimes in Higher Order Functions

我有一個 map: HashMap<&str, Vec<&str>>並且我正在嘗試創建一個反向查找 map HashMap<&str, &str> ,它從原始向量中的每個元素指向原始鍵。

例如 map 如下

{
  "k": vec!["a", "b"]
} 

會變成

{
  "a": "k",
  "b": "k",
} 

當我這樣做時,它工作得很好:

    let substitutes: HashMap<&str, Vec<&str>> = vec![("a", vec!["b", "c"])].into_iter().collect();
    
    // Below works fine
    let mut reversed: HashMap<&str, &str> = HashMap::new();
    for (&k, v) in substitutes.iter() {
        for vv in v.iter() {
            reversed.insert(vv, k);
        }
    }

但是,如果我嘗試使用高階函數來做到這一點,它就不起作用:

    // Below doesn't work
    let reversed_2: HashMap<&str, &str> = substitutes
        .iter()
        .flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
        .collect();

並給出以下錯誤:

error[E0373]: closure may outlive the current function, but it borrows `k`, which is owned by the current function
  --> src/main.rs:18:42
   |
18 |         .flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
   |                                          ^^^^^      - `k` is borrowed here
   |                                          |
   |                                          may outlive borrowed value `k`
   |
note: closure is returned here
  --> src/main.rs:18:29
   |
18 |         .flat_map(|(&k, v)| v.iter().map(|&vv| (vv, k)))
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `k` (and any other referenced variables), use the `move` keyword
   |
18 |         .flat_map(|(&k, v)| v.iter().map(move |&vv| (vv, k)))
   |                                          ^^^^^^^^^^

error: aborting due to previous error; 1 warning emitted

鑒於 vv 在 flat_map 下的同一個 scope 中,我正試圖圍繞vv如何比kflat_map

獲得更多關於我的 HOF 方法失敗的信息將非常有幫助。

操場

在這種情況下,編譯器的幫助是完全正確的:您需要在內部閉包上添加move

let reversed_2: HashMap<&str, &str> = substitutes
    .iter()
    .flat_map(|(&k, v)| v.iter().map(move |&vv| (vv, k)))
    .collect();

Rust 游樂場

當您使用來自周圍 scope 的變量創建匿名 function 時,內聯 function(稱為閉包)需要訪問這些變量。 默認情況下,它引用它們,使它們在封閉的 scope 中可用。 但是,在這種情況下,閉包會引用k並返回它,這意味着它可以逃脫封閉的 scope。

.flat_map(|(&k, v)| {
    // k is only valid in this anonymous function

    // a reference to k is returned out of map and also out of flat_map
    // (Note: no move)
    v.iter().map(|&vv| (vv, k))

    // the anonymous function ends, all references to k need to have ended
})

// A reference to k has been returned, even though k's lifetime has ended
// Compiler error!

當您切換到move閉包時,您無需引用封閉環境中的事物,而是獲得事物本身的所有權。 這使您可以返回k而不是對k的引用,從而回避了這個問題。

.flat_map(|(&k, v)| {
    // k is only valid in this anonymous function

    // k is moved out of the enclosing function and into the inner function
    // Because it owns k, it can return it
    // (Note: uses move)
    v.iter().map(move |&vv| (vv, k))

    // k has been moved out of this environment, so its lifetime does not end here
})

// k has been returned and is still alive

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM