Неизменные строки и клонирование - PullRequest
1 голос
/ 15 марта 2020

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

Заимствование не представляется возможным, так как мне пришлось бы иметь дело со ссылками и их временем жизни. Моя следующая мысль - использовать что-то вроде Rc или Cow struct. Но оборачивать все String чем-то вроде Rc кажется неестественным. В своем ограниченном опыте работы с Rust я никогда не видел никаких открытых структур владения / управления памятью, то есть Rc и Cow. Мне любопытно, как опытный разработчик Rust мог бы справиться с такой проблемой.

На самом ли деле в Rust можно представить структуры управления собственностью / памятью, такие как Rc и Cow? Должен ли я использовать ломтики?

use std::collections::HashSet;

#[derive(Debug)]
enum Check {
    Known(String),
    Duplicate(String),
    Missing(String),
    Unknown(String)
}

fn main() {
    let known_values: HashSet<_> = [
        "a".to_string(),
        "b".to_string(),
        "c".to_string()]
            .iter().cloned().collect();

    let provided_values = vec![
        "a".to_string(),
        "b".to_string(),
        "z".to_string(),
        "b".to_string()
    ];

    let mut found = HashSet::new();

    let mut check_values: Vec<_> = provided_values.iter().cloned()
        .map(|v| {
            if known_values.contains(&v) {
                if found.contains(&v) {
                    Check::Duplicate(v)
                } else {
                    found.insert(v.clone());
                    Check::Known(v)
                }
            } else {
                Check::Unknown(v)
            }
        }).collect();

    let missing = known_values.difference(&found);

    check_values = missing
        .cloned()
        .fold(check_values, |mut cv, m| {
            cv.push(Check::Missing(m));
            cv
        });

    println!("check_values: {:#?}", check_values);
}

1 Ответ

0 голосов
/ 15 марта 2020

Из обсуждения в комментариях к моему вопросу все клонирование неизменяемых String s в примере является правильным. Клонирование необходимо из-за того, что Rust обрабатывает память через владельца, а не по ссылке на других языках.

В лучшем случае, без использования Rc, я вижу некоторое сокращение клонирования с использованием семантики перемещения на provided_values .

Обновление : Интересное чтение

Cow не будет работать в моем примере, так как это связано с заимствованием ссылки. Rc было бы то, что я должен был бы использовать. В моем примере все должно быть преобразовано в Rc, но я вижу потенциал, что все это может быть скрыто через инкапсуляцию.


use std::collections::HashSet;
use std::rc::Rc;

#[derive(Debug)]
enum Check {
    Known(Rc<String>),
    Duplicate(Rc<String>),
    Missing(Rc<String>),
    Unknown(Rc<String>)
}

fn main() {
    let known_values: HashSet<_> = [
        Rc::new("a".to_string()),
        Rc::new("b".to_string()),
        Rc::new("c".to_string())]
            .iter().cloned().collect();

    let provided_values = vec![
        Rc::new("a".to_string()),
        Rc::new("b".to_string()),
        Rc::new("z".to_string()),
        Rc::new("b".to_string())
    ];

    let mut found = HashSet::new();

    let mut check_values: Vec<_> = provided_values.iter().cloned()
        .map(|v| {
            if known_values.contains(&v) {
                if found.contains(&v) {
                    Check::Duplicate(v)
                } else {
                    found.insert(v.clone());
                    Check::Known(v)
                }
            } else {
                Check::Unknown(v)
            }
        }).collect();

    let missing = known_values.difference(&found);

    check_values = missing
        .cloned()
        .fold(check_values, |mut cv, m| {
            cv.push(Check::Missing(m));
            cv
        });

    println!("check_values: {:#?}", check_values);
}

Детская площадка

...