Как итеративно вызвать функцию с аргументом ref и состоянием обновления?

#rust

#Ржавчина

Вопрос:

Это минимальный пример. У меня есть функция foo , которая берет ссылку на вектор и возвращает совершенно новый вектор. Затем есть еще одна функция bar , которая итеративно вызывает foo и обновляет свое состояние. Но я не могу заставить его скомпилироваться.

 fn foo(input: amp;Veclt;i32gt;) -gt; Veclt;i32gt; {  let len = input.len();  return input[0..len-1].to_vec(); }  fn bar() {  let input = vec![1,2,3,4,5];  let mut out = amp;input;  for _ in 0..2 {  out = foo(out);  } }  

Выдает эту ошибку:

 78 | out = foo(out);  | ^^^^^^^^  | |  | expected `amp;Veclt;i32gt;`, found struct `Vec`  | help: consider borrowing here: `amp;foo(out)`  

Так что это имеет смысл, так out как имеет несоответствующий тип amp;Veclt;i32gt; . Теперь, если я добавлю амперсанд перед foo(out) вызовом, то получу другую ошибку:

 78 | out = amp;foo(out);  | ^^^^---^- temporary value is freed at the end of this statement  | | |  | | borrow later used here  | creates a temporary which is freed while still in use  

Как правильно это исправить?

Ответ №1:

Чистый способ, если это возможно, состоит в том, чтобы последовательно придерживаться фактического значения вместо ссылки:

 fn bar() {  let input = vec![1,2,3,4,5];  let mut out = input;  for _ in 0..2 {  out = foo(amp;out);  } }  

или, что эквивалентно,

 fn bar() {  let input = vec![1,2,3,4,5];  let out = (0..2).fold(input, |prev, _| foo(amp;prev)); }  

Но если вам нужно будет продолжать использовать input позже, то вам придется найти какой-то другой способ сделать возвращаемое значение foo жить дольше, чем цикл, например

 fn bar() {  let input = vec![1,2,3,4,5];  let mut out_storage;  let mut out = amp;input;  for _ in 0..2 {  out_storage = foo(out);  out = amp;out_storage;  } }