arrays - significa - ¿Cómo devuelvo una matriz propia de una función?
que es un array en programacion (3)
=== EDITAR ===
en Rust 1 estable, ~[T]
convirtió en Vec<T>
, pero (sintaxis aparte) se aplica el mismo problema, ya que un Vec todavía tiene un propietario único. En pocas palabras, somethings
solo tiene una referencia a sí mismo y (a través de la referencia) no puede convertirse en el dueño de las thingies
. Enlace de Playground a la versión de Rust 1 aquí: https://play.rust-lang.org/?gist=50ec1acdc684e53fd5f9&version=stable .
El modelo de propiedad de Rust es bastante central para el idioma, por lo que para obtener más información, sugiero consultar la gran documentación oficial sobre propiedad y endeudamiento.
=== END EDIT ===
En Rust, el .
después de self
, self
-dereferences self
, entonces esta es la dereference of & pointer
que menciona el error.
Ahora la propiedad de thingies es la parte que no cannot move out of
la dereference:
let widget = Widget::new(); // widget owns the unique pointer to self
let wotsits = widget.somethings(); // if this worked, ownership of
// unique pointer to thingies would be
// moved to wotsits
Puede pedir prestada una referencia a thingies en su lugar:
fn somethings<''a>(&''a self) -> &''a~[int] {
&self.thingies
}
o devuelve explícitamente una copia de thingies
fn somethings(&self) -> ~[int] {
self.thingies.clone()
}
Soy un novato de Rust tratando de descubrir el idioma jugando con él. He tenido algunos problemas al intentar devolver una matriz desde una función:
struct Widget {
thingies: ~[int]
}
impl Widget {
fn new() -> Widget {
Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
}
fn somethings(&self) -> ~[int] {
self.thingies
}
}
fn main() {
let widget = Widget::new();
let wotsits = widget.somethings();
}
Esto por supuesto no compila con este error:
pointers.rs:11:8: 11:21 error: cannot move out of dereference of & pointer
pointers.rs:11 self.thingies
En caso de que este ejemplo de código parezca extraño, lo único que intento hacer es extraer una matriz de una estructura implementada. El puntero prestado no es importante, es solo la forma en que trato de almacenar los datos.
¿Algún consejo sobre cómo extraer mi matriz correctamente?
Por cierto, estoy usando Rust 0.8
La razón por la que su código no se compila es que un puntero único ~
puede tener solo un propietario. El compilador le impide escribir código propenso a errores. Puede decidir devolver una copia de thingies, una referencia a thingies o una porción de thingies (que es una referencia a los datos vectoriales o un segmento de los mismos).
Copiar solución
struct Widget {
thingies: ~[int]
}
impl Widget {
fn new() -> Widget {
Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
}
fn somethings(&self) -> ~[int] {
self.thingies.clone()
}
}
Solución de referencia
struct Widget {
thingies: ~[int]
}
impl Widget {
fn new() -> Widget {
Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
}
fn somethings<''a>(&''a self) -> &''a~[int] {
&self.thingies
}
}
Solución de rebanada
struct Widget {
thingies: ~[int]
}
impl Widget {
fn new() -> Widget {
Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
}
fn somethings<''a>(&''a self) -> &''a[int] {
self.thingies.as_slice()
}
}
Para comprender las soluciones de referencia y división, necesita comprender qué significa '': indica toda una vida, y &''a
es una manera de decirle al compilador que la referencia nunca debe sobrevivir al objeto al que hace referencia, que en este caso es un Widget .
Estas soluciones también tienen algunas limitaciones: no puede modificar un objeto al que está haciendo referencia actualmente porque al hacerlo se abre la posibilidad de que las referencias se vuelvan inválidas.
Por supuesto, puede modificar thingies si devuelve una referencia mutable. Se escribiría una referencia mutable con una vida útil &''a mut T
struct Widget {
thingies: ~[int]
}
impl Widget {
fn new() -> Widget {
Widget { thingies: ~[4, 8, 15, 16, 23, 42] }
}
fn somethings<''a>(&''a mut self) -> &''a mut ~[int] {
&mut self.thingies
}
}
Tenga en cuenta que creo que en Rust 0.8, necesita escribir &''self
lugar de &''a
porque las vidas con nombres personalizados aún no eran compatibles. También escribí esto en 0.9.
Editar: elimina declaraciones de tiempo de vida redundantes.
No puede salir del puntero prestado, como se explica en otras respuestas. Pero puede pasar self
por valor o por un puntero propio, luego podrá regresar su propio vector:
struct Widget {
thingies: ~[int]
}
impl Widget {
fn somethings(self) -> ~[int] {
self.thingies
}
}