如何将迭代器元素的类型强制为新类型或从新类型中强制?

时间:2019-06-06 06:21:28

标签: vector collections rust type-conversion newtype

用新类型做一些实验,寻找处理集合中元素转换的最有效,最符合人体工程学的方法。对于奇异值,相当标准的类型转换特性似乎可以正常工作:

pub struct Tag(String);

impl From<Tag> for String {
    fn from(v: Tag) -> String {
        v.0
    }
}

impl From<String> for Tag {
    fn from(v: String) -> Tag {
        Tag(v)
    }
}

impl AsRef<String> for Tag {
    fn as_ref(&self) -> &String {
        &self.0
    }
}

impl<'a> From<&'a Tag> for String {
    fn from(t: &Tag) -> String {
        t.0.clone()
    }
}

但是,当我要处理项目列表时,我开始遇到问题。说(出于说明目的),我有一个处理标签的函数,还有一些抽象函数,用于将字符串写入数据库:

fn process_item(tags: &Vec<Tag>) {
    process_array_of_strings(tags);
}

fn process_array_of_strings(strings: &Vec<String>) {
    // ...
}

这不会编译,因为Rust无法将tags强制转换为Vec<String>,在我看来,应该有比这更简单的方法:

fn process_item(tags: &Vec<Tag>) {
    let str_tags: Vec<String> = tags.iter().map(|t| t.into()).collect();
    process_array_of_strings(&str_tags);
}

...除了冗长之外,它还包含比我想要的更多的中间记忆。反向转换也是一个问题,但是大概可以用相同的方式实现。

这里可能还有其他事情,例如,我是否应该发送Vec引用而不是值,以及从引用类型实现类型转换是否是个好主意。

1 个答案:

答案 0 :(得分:1)

简单,只需使用泛型:

pub struct Tag(String);

impl AsRef<str> for Tag {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

fn process_item(tags: &[Tag]) {
    process_array_of_strings(tags);
}

fn process_array_of_strings<'a, T>(strings: &[T])
where
    T: AsRef<str>,
{
    // ...
}