当前位置: 首页 > 知识库问答 >
问题:

两个可变借款发生在同一行?

闻人宝
2023-03-14

我正试着用铁锈的雪球词干分析器板条箱来词干。这应该很简单,但借用检查器一直拒绝我的代码:

// 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);
    }
    // …
}

借用检查器说我在*t=stemmer行上有两个可变借用的stemmer。stem_str(t) 并拒绝我的代码。(第80行是input.lock()中的行所在的块。行()end。)

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()方法,我会得到一个字符串,但我不能只调用作为_str()并期望分配得到的

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个答案

韦宣
2023-03-14

stem_str的文档中:

它返回的str引用只有在您不再调用stem或stem_str时才有效;因此,如果范围中有这样的引用,Rust的borrowchecker将不允许调用其中一个函数。

据推测,这是因为词干分析器实现实际上有某种内部缓冲区,单词在词干时存储在那里。

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

我不能只调用作为_str()并期望分配获得的

编译器再次完全正确。您正试图创建一个值,引用它,存储引用,然后删除该值!这是一个内存漏洞,您不能这样做。

相反,收集字符串的向量:

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

我强烈建议大家阅读Rust编程语言,了解引用是如何工作的,以及它们阻止了什么。在涉及所有权的任何复杂问题之前和期间都要这样做。这些章节具体包括:

  • 所有权
  • 参考和借用
  • 一生

 类似资料:
  • 可变数据可以使用 &mut T 进行可变借用。这叫做可变引用(mutable reference),并赋予了借用者读/写访问能力。相反,&T 通过不可变引用(immutable reference)来借用数据,借用者可以读数据而不能更改数据: #[allow(dead_code)] #[derive(Clone, Copy)] struct Book { // `&'static str`

  • 问题 下面的代码显示,当影响一个数组到另一个数组时,这两个数组变得相互依赖。 我想知道为什么这与类型不同,因为如果我们有以下内容: 两个变量和引用的是同一个字符串,所以更改一个会影响另一个。

  • 在实践中考虑java并发的片段 同一本书的摘录- 考虑易失性变量的一个好方法是想象它们的行为大致类似于上面清单中的同步整数类,用调用get和set来替换易失性变量的读写。然而,访问易失性变量不执行锁定,因此不会导致执行线程阻塞,这使得易失性变量成为比同步更轻量级的同步机制。 线程限制的一种特殊情况适用于可变变量。对共享的易失性变量执行读-修改-写操作是安全的,只要确保该易失性变量仅从单个线程写入。

  • 如上所示,Owership让我们改变一个变量的值变得“复杂”,那能否像其他编程语言那样随意改变变量的值呢?答案是有的。 所有权系统允许我们通过“Borrowing”的方式达到这个目的。这个机制非常像其他编程语言中的“读写锁”,即同一时刻,只能拥有一个“写锁”,或只能拥有多个“读锁”,不允许“写锁”和“读锁”在同一时刻同时出现。当然这也是数据读写过程中保障一致性的典型做法。只不过Rust是在编译中完

  • 概述 所有权系统(Ownership System)是Rust语言最基本最独特也是最重要的特性之一。 Rust追求的目标是内存安全与运行效率,但是它却没有golang, java, python等语言的内存垃圾回收机制GC。 Rust语言号称,只要编译通过就不会崩溃(内存安全);拥有着零或者极小的运行时开销(运行效率)。这些优点也都得益于Rust的所有权系统。 所有权系统,包括三个重要的组成部分:

  • 首先,我尝试了这样的方法: 它不能被编译,因为 我想这个样本可以解决这个问题 它可以工作,但是为什么它现在与一起工作?