Ответ на задачу
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]
}
будет работать. Вам разрешено использовать изменяемый заем в l oop, только не злоупотребляйте этим, с точки зрения заемщиков. То, что вы фактически делаете, - это многократно повторное заимствование массива. Как всегда, компилятор очень полезен, если вы знаете, как его использовать.
Чтобы добраться до root проблемы, давайте рассмотрим только первые две итерации нашего l oop:
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
, поскольку оно возвращается. В следующей итерации l oop мы снова заимствуем arr
для 'arr
. Это нарушение правил заимствований.
Некоторые комментарии
Вы не делаете себе одолжение со всей этой изменчивостью. Это может проявиться в жалобе заемщика, которая будет позже приведена в main, когда вы пытаетесь удерживать изменяемую ссылку на значение в arr
и одновременно используете arr
, как это есть (конечно, если вы подумаете об этом! ) disallowed.
Кроме того, ваш алгоритм выбора случайной пустой плитки опасно спекулятивен. Что если в большом массиве есть только одна пустая плитка? Ваша реализация займет вечность. Сначала рассмотрите возможность фильтрации по всем индексам, указывающим на пустую плитку, затем выберите случайный индекс из этого набора, а затем верните запись, на которую указывает этот индекс. Я не буду предоставлять код для этого, вы получите это самостоятельно:)