Повторное использование переменных в Rust - PullRequest
0 голосов
/ 26 мая 2019

У меня есть следующий код:

let display_value = entry.path().display();
files_and_dirs.push(DiskEntry {
    path: display_value.to_string(),
    is_dir: is_dir(display_value.to_string()),
    name: display_value.to_string()
});

Если я напишу это так:

let display_value = entry.path().display();
let dir_name = display_value.to_string();
files_and_dirs.push(DiskEntry {
    path: dir_name,
    is_dir: is_dir(dir_name),
    name: dir_name
});

Я получаю следующую ошибку:

происходит движениепотому что dir_name имеет тип std::string::String, который не реализует черту Copy 1013 *

Я понимаю, что значения Rust перемещаются при присваивании.Я хочу объявить одну переменную и использовать ее несколько раз во втором блоке кода.Как мне это сделать?

Ответы [ 2 ]

4 голосов
/ 26 мая 2019

Ваши DiskEntry и is_dir предположительно определены следующим образом:

struct DiskEntry {
    path: String,
    is_dir: bool,
    name: String,
}

fn is_dir(path: String) -> bool {
    // ...
}

Каждый раз, когда существует переменная типа String, переменная должна иметь свою собственную копию строки в памяти.

Как подсказывает ошибка, вы могли бы исправить это путем клонирования:

let display_value = entry.path().display();
let dir_name = display_value.to_string();
files_and_dirs.push(DiskEntry {
    path: dir_name.clone(),
    is_dir: is_dir(dir_name.clone()),
    name: dir_name
});

Но вы должны избегать клонирования данных без необходимости, потому что они неэффективны. Клон, который очень легко удалить, находится в is_dir - должно быть совершенно очевидно, что этот метод не должен постоянно вступать во владение своим вводом. Вместо этого он может легко заимствовать его:

fn is_dir(path: &str) -> bool {
    // ...
}

И вы бы назвали это так, чтобы String был заимствован как &str:

is_dir(&dir_name),

Другой случай, вероятно, сложнее. Чтобы избежать клонирования, вам нужно заставить DiskEntry структуру заимствовать строки. Это будет выглядеть так:

struct DiskEntry<a'> {
    path: &'a str,
    is_dir: bool,
    name: &'a str,
}

let display_value = entry.path().display();
let dir_name = display_value.to_string();
files_and_dirs.push(DiskEntry {
    path: &dir_name,
    is_dir: is_dir(&dir_name),
    name: &dir_name
});

Однако это ограничит то, что вы можете делать с DiskEntry; в частности, он не может пережить переменную dir_name. Трудно понять, какие другие проблемы это может вызвать у вас, не зная более широкого контекста вашего кода, но это, вероятно, окажет более широкое влияние на другие структуры данных.

Учитывая, что вы, кажется, только изучаете Rust, если вы еще не знакомы с заимствованиями и сроками жизни, может быть проще всего принять этот дополнительный клон, пока у вас не появится лучшее понимание и вы не сможете сами сделать это.


Смотри также:

0 голосов
/ 26 мая 2019

Я хочу объявить одну переменную и использовать ее несколько раз во втором блоке кода.Как мне это сделать?

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

Если вы хотите использовать значение Clone переменная несколько раз - просто клонируйте ее.

Если вы хотите избежать повторения, вы можете дать вычислению имя с помощью замыкания.

let display_value = entry.path().display();
let dir_name = || display_value.to_string();
files_and_dirs.push(DiskEntry {
    path: dir_name(),
    is_dir: is_dir(dir_name()),
    name: dir_name()
});

Это не позволит вамиспользуйте значение несколько раз - оно создает новое значение при каждом вызове.

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