struct rust lifetime

¿Por qué usarías las mismas vidas para referencias en una estructura?



rust lifetime (1)

¿alguna vez hay beneficio para requerir referencias en una estructura tienen la misma vida

Sí, y va más allá de tener una estructura. Si las vidas fueron siempre distintas entre sí, entonces no se pudo escribir esta función:

fn foo<''a, ''b>(a: &''a str, b: &''b str) -> &str { // What lifetime to return? if (global_random_number() == 42) { a } else { b } }

Aplicando a la estructura, podrías tener algo como esto:

struct EvenOrOdd<''a, ''b> { even: &''a str, odd: &''b str, } impl<''a, ''b> EvenOrOdd<''a, ''b> { fn do_it(&self, i: u8) -> &str { if i % 2 == 0 { self.even } else { self.odd } } }

Tenga en cuenta que mientras esto se compila, no devuelve una cadena que puede sobrevivir a la estructura en sí , que no es lo que se pretendía. Este código falla, aunque debería poder funcionar:

fn foo<''a, ''b>(a: &''a str, b: &''b str) { let result = { EvenOrOdd { even: a, odd: b }.do_it(42) }; println!("{}", result); }

Esto funcionará con vidas unificadas:

struct EvenOrOdd<''a> { even: &''a str, odd: &''a str, } impl<''a> EvenOrOdd<''a> { fn do_it(&self, i: u8) -> &''a str { if i % 2 == 0 { self.even } else { self.odd } } }

Esto es lo opuesto a la respuesta vinculada, que tiene el comentario:

desea poder tomar un valor agregado y dividir partes de él después de usarlo

En este caso, queremos tomar un valor agregado y unificarlos .

En ocasiones más raras, puede necesitar enhebrar la aguja entre vidas distintas y unificadas:

struct EvenOrOdd<''a, ''b: ''a> { even: &''a str, odd: &''b str, } impl<''a, ''b> EvenOrOdd<''a, ''b> { fn do_it(&self, i: u8) -> &''a str { if i % 2 == 0 { self.even } else { self.odd } } }

Si bien esto es útil cuando es necesario, no puedo imaginar los lamentos y el crujir de dientes que estallarían si tuviéramos que escribirlo de esta manera todas las veces.

ignorando la escritura extra

Yo no lo haría Teniendo

foo<''a>(Bar<''a>)

es definitivamente mejor que

foo<''a, ''b'', ''c, ''d>(Bar<''a, ''b'', ''c, ''d>)

Cuando no se está beneficiando de los parámetros genéricos adicionales.

Esta pregunta es similar a ¿ Cuándo es útil definir múltiples vidas en una estructura? , pero con suerte lo suficientemente diferente. La respuesta a esa pregunta es útil, pero se centra en las ventajas de un enfoque (que utiliza tiempos de vida distintos para las referencias en la estructura), pero no en los inconvenientes (si corresponde). Esta pregunta, así, busca orientación sobre cómo elegir tiempos de vida al crear estructuras.

Llame a esto la versión atada porque se requiere que xey tengan la misma duración:

struct Foo<''a> { x: &''a i32, y: &''a i32, }

y llaman a esto la versión suelta porque las vidas pueden variar:

struct Foo<''a, ''b> { x: &''a i32, y: &''b i32, }

La respuesta a la pregunta a la que se hace referencia proporciona un caso claro en el que el código del cliente puede compilarse / ejecutarse dada la versión suelta , pero fallará en la versión vinculada . ¿No es cierto que cualquier código de cliente que funcione para la versión vinculada también funcionará para la versión suelta y se garantizará igual de seguro (es decir, seguro)? El anverso no es verdad La versión suelta es claramente más flexible desde la perspectiva del diseñador de estructuras. Teniendo en cuenta que es una respuesta buena / aceptada, la orientación podría ser: al usar referencias en una estructura siempre les da vidas distintas.

¿Cuál es el inconveniente de este consejo, ignorando el tipeo extra? Por ejemplo, ¿hay algún beneficio en requerir que las referencias en una estructura tengan la misma duración?