对Cow <str>切片的一般操作

时间:2015-08-04 10:24:45

标签: string vector rust

我正在尝试实现以下代码,该代码会从Cow<str>的切片中删除前缀。

fn remove_prefix(v: &mut [Cow<str>], prefix: &str) {
    for t in v.iter_mut() {
        match *t {
            Borrowed(&s) => s = s.trim_left_matches(prefix),
            Owned(s) => s = s.trim_left_matches(prefix).to_string(),
        }
    }
}

我有两个问题:

  1. 我无法将其编译 - 我尝试了&*的大量组合,但无济于事。

  2. 是否有更好的方法将函数应用于Cow<str>,而不必每次都match BorrowedOwned。我的意思是,似乎我应该能够执行类似*t = t.trim_left_matches(prefix)的操作,如果tBorrowed(str),则会将其保留为str(因为trim_left_matches允许),如果它是Owned(String),则将其保留为String。同样地,对于replace(),它会意识到必须将两者都转换为String(因为您无法在replace()上使用str)。是这样的吗?

2 个答案:

答案 0 :(得分:4)

问题#1强烈暗示你如何认为Rust中的模式匹配和/或指针工作与它们的实际工作方式并不完全一致。以下代码编译:

fn remove_prefix(v: &mut [Cow<str>], prefix: &str) {
    use std::borrow::Cow::*;
    for t in v.iter_mut() {
        match *t {
            Borrowed(ref mut s) => *s = s.trim_left_matches(prefix),
            Owned(ref mut s) => *s = s.trim_left_matches(prefix).to_string(),
        }
    }
}

如果您的案例Borrowed(&s)Borrowed(&str)匹配,则s的类型为str。这是不可能的:你绝对不能拥有动态大小类型的变量。这也适得其反。鉴于您希望修改 s,按值绑定它将无济于事。

您想要的是修改Borrowed变体中包含的内容。这意味着您需要一个指向该存储位置的可变指针。因此,Borrowed(ref mut s):这根本不会对Borrowed内的值进行解构。相反,它直接绑定到&str,意味着s属于&mut &str类型;指向a(指向str的指针)的可变指针。换句话说:一个指向字符串切片的可变指针。

此时,通过可变指针重新分配值来完成Borrowed的内容变更:*s = ...

最后,完全相同的推理适用于Owned情况:你试图绑定按值,然后改变它,这不可能做你想要的。而是通过可变指针绑定到存储位置,然后重新分配它。

关于问题#2 ......不是真的。这意味着某种重载,Rust没有做(通过慎重选择)。如果你正在做很多,你可以编写一个扩展特征,将{4}感兴趣的方法添加到其中。

答案 1 :(得分:3)

你绝对可以做到。

fn remove_prefix(v: &mut [Cow<str>], prefix: &str) {
    for t in v.iter_mut() {
        match *t {
            Cow::Borrowed(ref mut s) => *s = s.trim_left_matches(prefix),
            Cow::Owned(ref mut s) => *s = s.trim_left_matches(prefix).to_string(),
        }
    }
}

ref mut s表示“对值进行可变引用,并在模式中将其称为s”。因此,您s类型为&mut &str&mut String。然后,您必须使用*s = 来更改可变引用指向的内容(因此,更改Cow内的字符串)。