rust - pasar - matrices en c
¿Cuál es la forma idiomática de Rust de copiar/clonar un vector en una función parametrizada? (2)
Estoy tratando de escribir una función parametrizada que toma un vector inmutable, la clona o la copia, le hace algo al nuevo vector (como por ejemplo, barajarlo) y lo devuelve como un nuevo vector de propiedad. ¿Cómo se puede hacer esto y cuál es la forma más idiomática de hacerlo?
Intento # 1
pub fn shuffle<T>(vec: &mut [T]) {
// ... contents removed: it shuffles the vector in place
// ... so needs a mutable vector
}
pub fn shuffle_create_new<T: Clone>(vec: &[T]) -> Vec<T> {
let mut newvec = vec.clone();
shuffle(&mut newvec);
return newvec.to_owned();
}
Falla con:
error[E0596]: cannot borrow immutable borrowed content as mutable
--> src/main.rs:8:13
|
8 | shuffle(&mut newvec);
| ^^^^^^^^^^^ cannot borrow as mutable
aunque declaré newvec
como mutable. No entiendo porque
Intento # 2
pub fn shuffle_owned<T: Clone>(mut vec: Vec<T>) -> Vec<T> {
shuffle(&mut vec);
return vec;
}
Mientras esto se compila, no hace lo que quiero. El vector que se pasa a shuffle_owned
se traslada a la función, se baraja y luego se transfiere su propiedad a la persona que llama (a través del valor de retorno). Así se modifica el vector original.
Quiero saber cómo pasar un vector que no se modificará, pero que los valores se clonen en un nuevo vector en caja y se devuelvan cuando termine, como lo hace en un lenguaje de programación funcional que tiene datos inmutables (como Clojure).
Esto es probablemente lo que quieres:
pub fn copy_shuffle<T: Clone>(vec: &Vec<T>) -> Vec<T> {
let mut vec = vec.clone();
shuffle(&mut vec);
vec
}
o
pub fn copy_shuffle<T: Clone>(vec: &[T]) -> Vec<T> {
let mut vec = vec.to_vec();
shuffle(&mut vec);
vec
}
Su intento # 1 es casi correcto, solo tiene que pasar to_owned()
a la primera línea:
fn shuffle<T>(vec: &mut [T]) {
// ...
}
fn shuffle_create_new<T: Clone>(vec: &[T]) -> Vec<T> {
let mut newvec = vec.to_vec();
shuffle(&mut newvec);
newvec
}
Esto sucede porque llamar a clone()
en una división le devolverá una porción (es decir, &[T]
), y no puede pasar de &[T]
a &mut [T]
porque no puede elegir la mutabilidad de una referencia (puntero prestado). Sin embargo, cuando llamas to_owned()
, to_owned()
una nueva instancia de Vec<T>
y puedes ponerla en una variable mutable para obtener un vector mutable.
A partir de Rust 1.0, se puede usar el método slice::to_vec
o to_owned()
del rasgo ToOwned
para crear Vec<T>
desde &[T]
.
Ahora también hay varias formas de obtener &mut [T]
de Vec<T>
: la notación de corte ( &mut vec[..]
), la conversión deref ( &mut *vec
) o la llamada de método directo ( vec.as_mut_slice()
, aunque este está en desuso):