Tiempos de Vida en Llamadas a Función
Además de tomar prestados sus argumentos, una función puede devolver un valor que se ha tomado prestado:
#[derive(Debug)] struct Point(i32, i32); fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point { if p1.0 < p2.0 { p1 } else { p2 } } fn main() { let p1: Point = Point(10, 10); let p2: Point = Point(20, 20); let p3: &Point = left_most(&p1, &p2); println!("left-most point: {:?}", p3); }
'a
es un parámetro genérico que infiere el compilador.- Los tiempos de vida comienzan por
'
y'a
suele ser un nombre predeterminado habitual. - Lee
&'a Point
como “unPoint
prestado que es válido al menos durante el tiempo de vida dea
”.- La parte al menos es importante cuando los parámetros están en ámbitos distintos.
En el ejemplo anterior, prueba lo siguiente:
-
Mueve la declaración de
p2
yp3
a un nuevo ámbito ({ ... }
), lo que dará como resultado el siguiente código:#[derive(Debug)] struct Point(i32, i32); fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point { if p1.0 < p2.0 { p1 } else { p2 } } fn main() { let p1: Point = Point(10, 10); let p3: &Point; { let p2: Point = Point(20, 20); p3 = left_most(&p1, &p2); } println!("left-most point: {:?}", p3); }
Ten en cuenta que no se puede compilar, ya que
p3
dura más tiempo quep2
. -
Restablece el espacio de trabajo y cambia la firma de la función a
fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point
. No se compilará porque la relación entre los tiempos de vida de'a
y'b
no está clara. -
Otra forma de explicarlo:
- Una función toma prestadas dos referencias a dos valores y devuelve otra referencia.
- Esta debe proceder de una de esas dos entradas (o de una variable global).
- ¿Cuál de ellas es? El compilador debe saberlo para que, en el sitio de la llamada, la referencia devuelta no se use durante más tiempo que una variable de la que procede la referencia.