Can someone enlighten me about lifetimes? I don't quite get the point why we need to expand them some times.
Question 1
We need to expand lifetimes in structs that contain references:
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let x; // -+ x goes into scope
// |
{ // |
let y = &5; // ---+ y goes into scope
let f = Foo { x: y }; // ---+ f goes into scope
x = &f.x; // | | error here
} // ---+ f and y go out of scope
// |
println!("{}", x); // |
}
However, even if the lifetime would not be explicitly defined I would expect the same result. Foo gets destroyed and thus x becomes invalid. What good does it do to explicitly expand the lifetime in the struct for Foo?
Question 2
How is it useful to have two named lifetimes in a function? e.g.
fn bar<'a, 'b>(x: &'a i32, y: &'b i32) -> ();
What difference does it make that the lifetimes are named uniquely? They both will be valid in the scope of the function anyway (they will have the same scope). Can someone give me an example where uniquely named lifetimes are necessary? What are they good for?
Question 3
This is somewhat of a bonus question. On the same page I also found this:
struct Foo<'a> {
x: &'a i32,
}
impl<'a> Foo<'a> {
fn x(&self) -> &'a i32 { self.x }
}
fn main() {
let y = &5; // this is the same as `let _y = 5; let y = &_y;`
let f = Foo { x: y };
println!("x is: {}", f.x());
}
I am referring to the function in the implementation. What is the reason that I have to write:
fn x(&self)
the &self confuses me. Is this just a convention? I mean why can't I write
fn x()
instead? After all the function call is
f.x() // without parameter
What happens if I have a function definition in the implementation like this
fn x(y: i32, &self, z: i32)
Is this illegal, or can I still call the function like
f.x(2,3) // where y=2 and z=3