2016-01-05 2 views
3

Я хочу вернуть итератор (в частности, Filter). Я использовал previous answer, который предлагает вернуть итератор в коробке. Проблема заключается в том, что мой фильтр захватывает self и я получаю:Как установить время жизни для закрытия в коробке закрытия `self`?

error: closure may outlive the current function, but it borrows self , which is owned by the current function

Но я думаю, что я быть четко указано, что self имеет срок службы 'a и так ли Box я возвращаюсь:

fn occupied_iter_x<'a>(&'a self) -> Box<Iterator<Item=i32> + 'a> { 
    Box::new((0..32).filter(|&pos| match self.at(pos) { Occupied::Empty => false, _ => true })) 
} 

Этот является попыткой упростить мое первое усилие, когда я создал новый FooIterator, который, в принципе, имеет ссылку на self.

Если я использую большую часть того же синтаксис просто захватить self в качестве члена ссылки на него работает отлично:

struct Foo { junk: i32 } 
struct FooIterator<'a> { foo: &'a Foo } 
impl Foo { 
    fn foo<'a>(&'a self) -> Box<FooIterator<'a>> { 
     Box::new(FooIterator { foo: self }) 
    }  
} 

ответ

5

Вы получаете сообщение об ошибке, потому что ваше закрытие получает ссылку на self, который сам по себе является ссылкой. Однако, поскольку ссылка указывает на локальную переменную, эта ссылка становится недействительной, как только функция вернется.

Чтобы исправить это, добавьте ключевое слово move перед закрытием. Это дает команду компилятору переместить закрытые переменные в закрытии, а не передать ссылку на эти переменные на закрытие.

fn occupied_iter_x<'a>(&'a self) -> Box<Iterator<Item=i32> + 'a> { 
    Box::new((0..32).filter(move |&pos| match self.at(pos) { Occupied::Empty => false, _ => true })) 
} 
+0

Итак, вы говорите, что закрытие неявно захватывает '& self', у которого есть собственное время жизни, не зависящее от' 'a'. Это делает это, потому что закрытие фиксируется ссылкой? Но 'self' неизменен (легко проверяется с помощью теста self = self), так почему бы ему просто не захватить его по стоимости? –

+2

@BenJackson, если вы не используете ключевое слово 'move', закрытие будет захватывать его среду по ссылке (в этом случае среда будет содержать ссылку на & self, то есть двойную ссылку). Если вы это сделаете, он будет захватывать его по значению. Вот как работают замыкания в Rust. –

Смежные вопросы