两个可变借词发生在同一条线上?

时间:2016-12-19 16:39:41

标签: rust borrow-checker

我正在尝试使用Rust中的Snowball stemmer crate来阻止单词的向量。它应该很简单,但借用检查器一直拒绝我的代码:

// Read user input
let input = stdin();
let mut stemmer = Stemmer::new("english").unwrap();
for line in input.lock().lines() {
    let line = line.unwrap();
    let mut query: Vec<_> = line.split_whitespace().collect();
    for t in &mut query {
        *t = stemmer.stem_str(t);
    }
    // …
}

借阅检查器说我在行stemmer上有两个*t = stemmer.stem_str(t);的可变借词并拒绝我的代码。 (第80行是for line in input.lock().lines()的块结束的地方。)

57  18 error    E0499  cannot borrow `stemmer` as mutable more than once at a time (first mutable borrow occurs here) (rust-cargo)
57  18 error    E0499  cannot borrow `stemmer` as mutable more than once at a time (second mutable borrow occurs here) (rust-cargo)
80   5 info     E0499  first borrow ends here (rust-cargo)

如果我直接调用stem()方法,我会收到String,但我不能只调用as_str()并期望将获得的&str分配给*t,因为借用检查员抱怨“借来的价值不够长”。

57  18 error           borrowed value does not live long enough (temporary value created here) (rust-cargo)
57  18 info            consider using a `let` binding to increase its lifetime (rust-cargo)
57  42 info            temporary value only lives until here (rust-cargo)
80   5 info            temporary value needs to live until here (rust-cargo)

我不确定这是否与此库的实现细节有关,但我真的感到困在这里。我从未预料到输入的输入会如此困难。

1 个答案:

答案 0 :(得分:4)

来自documentation of stem_str

  

只要你不再调用stem或stem_str,它返回的str引用才有效;因此,如果你在范围内有这样的参考,那么Rust的借阅者不会让其中一个人发挥作用。

据推测,这是因为词干分析器的实现实际上有一些内部缓冲区,其中的单词在被阻止时被存储。

这就是为什么在保持对字符串的引用时不能两次调用stem_str的原因;这样做会使第一个字符串无效!!。

  

我无法致电as_str()并期望将获得的&str分配回*t

编译器再次绝对正确。您正在尝试创建一个值,对其进行引用,存储引用,然后删除该值!这是一个记忆漏洞而你无法做到。

相反,收集String s:

的向量
for line in input.lock().lines() {
    let line = line.unwrap();
    let mut query: Vec<_> = line.split_whitespace()
        .map(|t| stemmer.stem(t))
        .collect();
}

我强烈建议您阅读The Rust Programming Language并了解参考资料的工作原理及其预防措施。在之前执行此,在期间进入任何复杂的所有权。这些章节具体说明: