我正在学习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;
型
从而使数组发生变化,以替换空值。
1条答案
按热度按时间4jb9z9bj1#
问题的答案
字符串
你可以在循环中使用一个可变的borrow,只是不要滥用它,从borrowcheckers的Angular 来看。你实际上做的是可变地重复借用一个数组。和往常一样,编译器是超级有用的,如果你知道如何使用它。
为了找到问题的根源,让我们看看循环的前两次迭代:
型
}
编译器告诉我们:
arr
的借用(称为tile
)必须与数组本身(称为'arr
)具有相同的生存期。在下一次循环迭代中,我们再次借用arr
来替换'arr
。这违反了借款人规则。一些评论
你这样做对你自己没有好处。这可能会在稍后的main中的borrowchecker抱怨中表现出来,当你试图在
arr
中保存一个值的可变引用并同时使用arr
时,就像这样(当然,如果你想一下的话!)不允许。此外,你选择一个随机的空瓷砖的算法是危险的投机。如果在一个大数组中只有一个空的瓦片怎么办?您的实施将永远。考虑首先过滤指向空图块的所有索引,然后从该集合中选择随机索引,然后返回该索引指向的条目。我不会为这个提供代码,你自己得到了这个:)