Reading the book, I was trying to add methods to the "cons-list" type, defined as
enum List<T> {
Item(T, Box<List<T>>),
Null,
}
The first method I tried to implement was from_slice
which build a cons list from &[T]
.
However the borrow-checker does not accept the following implementation
impl<T> List<T> {
pub fn from_slice(v: &[T]) -> List<T>
where T: Copy
{
let n = v.len();
let lst = List::Null;
for i in (0..n).rev() {
let lst = List::Item(v[i], Box::new(lst));
}
lst
}
}
Why is this not accepted and what should I do to convince the borrow checker that this program is safe?
Interestingly expanding the above for
loop does not give any compilation error (the borrow checker likely realizes that the previous lst
is being shadowed after each line).
// Expanding the previous function for v = [0, 1, 2]
let lst = List::Null;
let lst = List::Item(0, Box::new(lst));
let lst = List::Item(1, Box::new(lst));
let lst = List::Item(2, Box::new(lst));
By doing let lst = ...
inside the for
loop, you're creating a new lst
binding which is immediately dropped after that line. What you want instead is to make the lst
one level up mut
and re-assign to that:
impl<T> List<T> {
pub fn from_slice(v: &[T]) -> List<T>
where
T: Copy,
{
let n = v.len();
let mut lst = List::Null;
for i in (0..n).rev() {
lst = List::Item(v[i], Box::new(lst));
}
lst
}
}