[英]Returning a mutable reference in Rust
我正在學習 Rust,如果這是一個微不足道的問題,我深表歉意。 我用谷歌搜索了一個小時無濟於事。
我有一個枚舉值數組。 我希望在該數組中找到一個與特定模式匹配的隨機位置並返回對其的可變引用,目的是修改該位置的元素。
enum Tile {
Empty,
... // Other enum values
}
fn random_empty_tile(arr: &mut [Tile]) -> &mut Tile {
loop {
let i = rand::thread_rng().gen_range(0, arr.len());
let tile = &mut arr[i];
if let Tile::Empty = tile {
return tile;
}
}
}
借用檢查器在這里抱怨兩件具體的事情。 第一個是arr.len()
調用。 這是不允許的,因為它需要對arr
進行不可變引用,並且我們已經通過參數獲得了對arr
的可變引用。 因此,不能進行其他引用,並且不允許調用。
第二個是return tile
。 這會失敗,因為借用檢查器無法證明此引用的生命周期與arr
本身的生命周期相同,因此返回是不安全的。
我認為上面對錯誤的描述是正確的; 我想我明白出了什么問題。 不幸的是,我不知道如何解決這些問題。 如果有人可以提供一個慣用的解決方案來實現這種行為,將不勝感激。
最后,我希望做到以下幾點:
let mut arr = [whatever];
let empty_element = random_empty_tile(&mut arr);
*empty_element = Tile::SomeOtherValue;
因此改變數組以替換空值。
問題的答案
fn random_empty_tile(arr: &mut [Tile]) -> &mut Tile {
let len = arr.len();
let mut the_chosen_i = 0;
loop {
let i = rand::thread_rng().gen_range(0, len);
let tile = &mut arr[i];
if let Tile::Empty = tile {
the_chosen_i = i;
break;
}
}
&mut arr[the_chosen_i]
}
將工作。 您可以在循環中使用可變借用,只是不要濫用它,從借用檢查器的角度來看。 您正在有效地做的是可變地反復重新借用數組。 與往常一樣,編譯器非常有用,如果您知道如何使用它。
為了找到問題的根源,讓我們看看循環的前兩次迭代:
fn random_empty_tile_2<'arr>(arr: &'arr mut [Tile]) -> &'arr mut Tile {
let len = arr.len();
// First loop iteration
{
let i = thread_rng().gen_range(0, len);
let tile = &mut arr[i]; // Lifetime: 'arr
if let Tile::Empty = tile {
return tile;
}
}
// Second loop iteration
{
let i = thread_rng().gen_range(0, len);
let tile = &mut arr[i]; // Lifetime: 'arr
if let Tile::Empty = tile {
return tile;
}
}
unreachable!();
}
編譯器告訴我們: arr
的借用,稱為tile
必須與數組本身具有相同的生命周期,稱為'arr
,因為它被返回。 在一個循環周期,我們再次借用arr
為'arr
。 這違反了borrowcheckers 規則。
一些評論
你對所有這些可變性沒有幫助。 這可能會表現在借用檢查器稍后在 main 中抱怨時,當您嘗試在arr
保存對值的可變引用並同時使用arr
時,因為這是(當然,如果您考慮一下!)是不允許的。
此外,您選擇隨機空圖塊的算法具有危險的推測性。 如果大數組中只有一個空圖塊怎么辦? 您的實施將花費很長時間。 考慮首先過濾所有指向空圖塊的索引,然后從該集合中選擇一個隨機索引,然后返回該索引指向的條目。 我不會為此提供代碼,你自己得到的:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.