2015-02-23 4 views
5

Я пытаюсь научить себя немного ржавчины, и написал что-то, что выглядит как:Как установить время жизни возвращаемого значения как время жизни переменной, которую я перемещаю в нее?

let args:Vec<String> = env::args().collect(); 
let parsed = parser::sys(args.as_slice()); 

...

pub fn sys<'a>(args:&'a [String]) -> Parsed<'a> { 
    parsed(args) 
} 

где parsed это функция, которая анализирует и загружает конфиги.

Это прекрасно работает. Теперь я пытаюсь абстрагироваться от явного вызова env::args() и скрыть его в вызове sys, поэтому я пишу новую версию sys

pub fn sys<'a>() -> Parsed<'a> { 
    let args:Vec<String> = env::args().collect(); 
    parsed(args.as_slice()) 
} 

И это терпит неудачу с:

error: `args` does not live long enough 
src/test.rs:66  parsed(args.as_slice()) 

Я думаю, что ошибка заключается в том, что компилятор не может сделать вывод о том, что я хочу, чтобы время жизни этой вновь созданной структуры являлось временем жизни переменной, в которую я хочу переместить это. Это верно? Как я могу пояснить время жизни для этого возвращаемого значения/исправить это?

ответ

3

Я думаю, что ошибка связана с тем, что компилятор не может сделать вывод о том, что я хочу, чтобы время жизни этой вновь созданной структуры являлось временем жизни переменной, в которую я хочу переместить это.

Собственно, нет.

Ошибка в том, что вы пытаетесь создать ссылки в переменную args, которая больше не будет находиться в силе после возвращения из sysargs так как локальные переменные, и, таким образом, падаете в конце sys.

Если вы хотите использовать ссылки, вы могли бы поставить sys с &'a mut Vec<String> (пусто), заполнить его в sys и возвращать ссылки на него:

pub fn sys<'a>(args: &'a mut Vec<String>) -> Parsed<'a> { 
    *args = env::args().collect(); 
    parsed(args.as_slice()) 
} 

, который гарантирует, что args переживет sys вызов. Это займет args за время жизни результата.

Другое решение состоит в том, чтобы покончить с 'a и просто иметь Parsed свои элементы, а не ссылаться на них; однако без определения Parsed Я не могу посоветовать, как это лучше всего сделать.

+0

Невозможно «переместить» аргументы из sys, например. например std: перемещение или копирование elision. Следующие работы, но там тоже я назначаю локальную переменную, но почему-то я думаю, что компилятор знает, как ее переместить: pub fn contents (источник: & String) -> Vec { let mut reader = BufferedReader: : new (Файл :: open (& Path :: new (источник))); reader.lines(). Map (| l | l.unwrap()). Collect() } – sgldiv

+0

@sgldiv 'Reader :: lines' является' Iterator ', а не' Iterator '. Вы возвращаете 'Vec ', который имеет полное право собственности на все данные, которые возвращены. Нет ничего, из которого заимствовано возвращаемое значение и которое магический манер движется без малейшего движения. – delnan

+0

Это имеет смысл. Благодаря! – sgldiv

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