Как правильно выполнить проверку заимствования при условном создании вектора - PullRequest
0 голосов
/ 30 апреля 2020

Итак, я хочу создать вектор (потому что длина не известна во время компиляции), который не является изменяемым (потому что, когда я создаю его, я изменяю его в последний раз). По сути, я либо получаю значение из файла, либо значения из аргументов командной строки, а затем перебираю эти значения позже.

Я хотел сделать

/* other file
pub struct Settings {
  pub repo_name: String,
}
pub fn get_settings() -> Result<Settings, ConfigError>
*/

let settings = get_settings();
let args = App.blah.get_matches(); //clap::ArgMatches
let repos: Vec<_>;
if args.is_present("repo") {
    repos = args.values_of("repo").unwrap().collect(); // https://docs.rs/clap/2.31.1/clap/struct.ArgMatches.html#method.values_of
} else {
    // I want repos to own the value I clone here
    repos = vec![settings.repo_name.clone()];
}

Для этого, ve c! хотел ссылку. Если я использовал ссылку с clone (), срок действия ссылки заканчивался до назначения. Если я создал новую переменную, время жизни заканчивается в конце блока. Если я напрямую позаимствовал из настроек, позже заблокировал другие варианты использования.

В конце концов, я заставил его работать с

let default_repo = settings.repo_name.clone();
if args.is_present("repo") {
    repos = args.values_of("repo").unwrap().collect();
} else {
    repos = vec![&default_repo];
}

Но мне интересно, есть ли способ на самом деле дает repos владение значением в новом векторе?

1 Ответ

2 голосов
/ 30 апреля 2020

Я думаю, вам нужно выбрать тип repos.

  • repos = args.values_of("repo").unwrap().collect() создает Vec<&str>, то есть вектор срезов
  • repos = vec![settings.repo_name.clone()]; создает a Vec<String>

Если вы решите go с Vec<&str> (меньше копий, но вам нужно больше заботиться о продолжительности жизни), вы можете изменить секунду на repos = vec![&settings.repo_name]. Чтобы это работало, settings должен прожить достаточно долго.

Если вы решите go с помощью Vec<String>, вы можете изменить первое значение на repos = args.values_of("repo").unwrap().map(|s|s.to_string()).collect().

Другой вариант: следующее: полностью опустить вектор и - вместо этого - ввести другую функцию, использующую итератор, и просто вызвать эту функцию либо с values_of("repo").unwrap(), либо с std::iter::once(repo_name).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...