2016-01-12 2 views
5

У меня есть функция, которая выглядит как:модифицирующих `iter` цепь использовать` and_then` и т.д.

type Attributes = HashMap<String, json::Json>; 
type Store = Arc<RwLock<HashMap<String, RwLock<Attributes>>>>; 

fn get(store: &Store, key: &str) -> Option<Attributes> { 
    store.read().iter() 
     .filter_map(|g| (*g).get(key)) 
     .filter_map(|v| v.read().ok()) 
     .map(|v| (*v).clone()) 
     .next() 
} 

Это компилирует и работает просто отлично. Тем не менее, для моего собственного назидания, я пытался изменить это, чтобы использовать стандартные Result/Option методы (без преобразования LockResult к Iter), что-то вроде:

store.read().ok() 
    .and_then(|g| (*g).get(key)) 
    .and_then(|v| v.read().ok()) 
    .map(|v| (*v).clone()); 

Но это говорит мне, что g does not live long enough. Я попытался добавить ref и as_ref в разные места, но не могу его скомпилировать. Что мне не хватает?

Я знаю, что могу заставить его работать как:

store.read().ok() 
     .and_then(|g| { 
      (*g).get(key) 
       .and_then(|v| v.read().ok()) 
       .map(|v| (*v).clone()) 
     }) 

Но я хотел бы быть в состоянии цепи него, как в случае iter.

+0

(Потенциально вопрос о нобе) Разве это не разница между 'iter()' и 'in_iter()'? Возможно, вы захотите использовать 'in_iter()', чтобы переместить право собственности на остальную часть вашей цепочки, чтобы ваши ссылки работали повсюду? –

+0

@SimonWhitehead, спасибо за комментарий! Да, я думаю, что это как раз разница между 'iter' и' in_iter', но наоборот. Я ** ** хочу использовать 'iter', а не' in_iter', и на самом деле я хочу вариант 'and_then', который делает что-то вроде' iter', но я не могу понять правильную комбинацию 'as_ref' и т. д., что делает это. Когда я изменяю первый пример выше, чтобы использовать 'in_iter', я получаю те же сообщения об ошибках, что и второй пример. –

+0

Не думаю, что вы могли бы собрать MVCE на манеже для меня/других, чтобы возиться с ним? –

ответ

3

ОК, компилятор действительно возится со мной сегодня вечером.

Я получил это колдовство скомпилировать:

fn get(store: &Store, key: &str) -> Option<Attributes> { 
    let r = store.read(); 
    let x = r.as_ref().ok() 
     .and_then(|g| (*g).get(key)) 
     .and_then(|v| v.read().ok()) 
     .map(|v| (*v).clone()); 
    x 
} 

Если вы рядный либо r или x, вы получите еще does not live long enough ошибку снова. Я не уверен, почему, так как в принципе блокировка охранника должна оставаться активной как временная до конца заявления.

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