Translate

jueves, 10 de agosto de 2023

Duración de las llamadas a funciones en Rust

 


Además de tomar prestados sus argumentos, una función puede devolver un valor 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, lo infiere el compilador.
  • Los tiempos de vida comienzan con ' y 'a es un nombre predeterminado típico.
  • Lea &'a Point como “un Punto prestado que es válido por lo menos durante el tiempo de vida a”.
  • La parte al menos es importante cuando los parámetros están en diferentes ámbitos.

En el ejemplo anterior, intente lo siguiente:

Mueva la declaración de p2 y p3 a un nuevo ámbito ({ ... }), lo que da 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);

}


Esto no compila ya que p3 sobrevive a p2.

Restablezca el espacio de trabajo y cambie la firma de la función a fn left_most<'a, 'b>(p1: &'a Point, p2: &'a Point) -> &'b Point. Esto no se compilará porque la relación entre las vidas 'a y 'b no está clara.

Otra forma de explicarlo:

  • Una función toma prestadas dos referencias a dos valores y la función devuelve otra referencia.
  • Debe haber venido de una de esas dos entradas (o de una variable global).
  • ¿Cuál es? El compilador necesita saber, por lo que en el sitio de la llamada, la referencia devuelta no se usa por más tiempo que una variable de donde proviene la referencia.