首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在圈内借入

在圈内借入
EN

Stack Overflow用户
提问于 2022-06-26 16:41:08
回答 1查看 84关注 0票数 2

经过多年的C++学习,我正在努力学习锈病。我有一种情况,编译器抱怨的是一个借用,这似乎并不重要,它是可变的还是不变的。我似乎无法在以:for item in self.func.drain(..)开头的循环中使用self作为参数。

我尝试调用appropriate()作为一个函数:

代码语言:javascript
复制
Self::appropriate(&self,&item,index)

我试过用这个方法:

代码语言:javascript
复制
self.appropriate(&item,index)

但是,在这两种情况下,我都得到了相同的消息:函数或方法appropriate()意味着检查其参数之间的关系,并返回一个bool而不修改任何内容。如何在不违反借用规则的情况下调用self上的函数或方法?

这个程序是从exercism.org中学习的,不包括main(),所以它不会运行,但是除了有问题的错误外,它几乎应该编译。下面是我的代码:

代码语言:javascript
复制
use std::collections::HashMap;

pub type Value = i32;
pub type Result = std::result::Result<(), Error>;

pub struct Forth {
    v: Vec<Value>,
    f: HashMap<String,usize>,
    s: Vec<Vec<String>>,
    func: Vec<String>
}


#[derive(Debug, PartialEq)]
pub enum Error {
    DivisionByZero,
    StackUnderflow,
    UnknownWord,
    InvalidWord,
}

impl Forth {
    pub fn new() -> Forth {
        let mut temp: Vec<Vec<String>> = Vec::new();
        temp.push(Vec::new());
        Forth{v: Vec::<Value>::new(), f: HashMap::new(), s: temp, func: Vec::new()}
    }

    pub fn stack(&self) -> &[Value] {
        &self.v
    }

    pub fn eval(&mut self, input: &str) -> Result {
        self.v.clear();
        self.s[0].clear();

        let mut count = 0;

        {
            let temp: Vec<&str> = input.split(' ').collect();
            let n = temp.len() as i32;
            for x in 0..n as usize {
                self.s[0].push(String::from(temp[x]));
            }
        }

        let mut collecting = false;
        let mut xlist: Vec<(usize,usize)> = Vec::new();
        let mut sx: usize = 0;
        let mut z: i32 = -1;
        let mut x: usize;
        let mut n: usize = self.s[0].len();

        loop {
            count += 1;
            if count > 20 {break;}

            z += 1;
            x = z as usize;
            if x >= n {break;}
            z = x as i32;
            
            let word = &self.s[sx][x];

            if word == ";" {
                if collecting {
                    collecting = false;
                    let index: usize = self.s.len();
                    self.s.push(Vec::<String>::new());
                    for item in self.func.drain(..) {
                        if self.s[index].len() > 0 &&
                            Self::appropriate(&self,&item,index)
                        {
                            let sx = *self.f.get(&self.s[index][0]).unwrap();
                            let n = self.s[sx].len();
                            for x in 1..n as usize {
                                let symbol = self.s[sx][x].clone();
                                self.s[index].push(symbol);
                            }
                        }
                        else {
                            self.s[index].push(item);
                        }
                    }
                    self.f.insert(self.s[index][0].clone(), index);
                    self.func.clear();
                    continue;
                }
                if 0 < xlist.len() {
                    (x, n) = xlist.pop().unwrap();
                    continue;
                }
                return Err(Error::InvalidWord);
            }
            if collecting {
                self.func.push(String::from(word));
                continue;
            }
            if Self::is_op(word) {
                if self.v.len() < 2 {
                    return Err(Error::StackUnderflow);
                }
                let b = self.v.pop().unwrap();
                let a = self.v.pop().unwrap();
                let c = match word.as_str() {
                    "+" => a + b,
                    "-" => a - b,
                    "*" => a * b,
                    "/" => {if b == 0 {return Err(Error::DivisionByZero);} a / b},
                    _ => 0
                };
                self.v.push(c);
                continue;
            }
            match word.parse::<Value>() {
                Ok(value) => { self.v.push(value); continue;},
                _ => {}
            }
            if word == ":" {
                collecting = true;
                self.func.clear();
                continue;
            }
            if word == "drop" {
                if self.v.len() < 1 {
                    return Err(Error::StackUnderflow);
                }
                self.v.pop();
                continue;
            }
            if word == "dup" {
                if self.v.len() < 1 {
                    return Err(Error::StackUnderflow);
                }
                let temp = self.v[self.v.len() - 1];
                self.v.push(temp);
                continue;
            }
            if !self.f.contains_key(word) {
                return Err(Error::UnknownWord);
            }
            xlist.push((sx,n));
            sx = *self.f.get(word).unwrap();
            n = self.s[sx].len();
            z = 0;
        }
        Ok(())
    }

    fn is_op(input: &str) -> bool {
        match input {"+"|"-"|"*"|"/" => true, _ => false}
    }

    fn appropriate(&self, item:&str, index:usize) -> bool
    {
        false
    }

    fn prev_def_is_short(&self, index: usize) -> bool {
        if index >= self.s.len() {
            false
        }
        else {
            if let Some(&sx) = self.f.get(&self.func[0]) {
                self.s[sx].len() == 2
            }
            else {
                false
            }
        }
    }

}

错误消息与对appropriate()的调用有关。我甚至还没有编写函数的主体;我想先得到正确的参数。编译器的抱怨是:

代码语言:javascript
复制
As a subroutine call

error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
  --> src/lib.rs:85:47
   |
81 |                     for item in self.func.drain(..) {
   |                                 -------------------
   |                                 |
   |                                 mutable borrow occurs here
   |                                 mutable borrow later used here
...
85 |                             Self::appropriate(&self,&item,index)
   |                                               ^^^^^ immutable borrow occurs here

For more information about this error, try `rustc --explain E0502`.


as a method call

error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
  --> src/lib.rs:85:29
   |
81 |                     for item in self.func.drain(..) {
   |                                 -------------------
   |                                 |
   |                                 mutable borrow occurs here
   |                                 mutable borrow later used here
...
85 |                             self.appropriate(&item,index)
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow occurs here

For more information about this error, try `rustc --explain E0502`.

有什么规范的方法来处理这种情况吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-26 17:59:38

问题是,self.func.drain()将使用self.func中包含的元素,因此整个for循环在self.func上需要独占 (&mut)访问。如果在迭代期间需要全局传递对self的引用,那么它的func成员可能是可访问的,而循环拥有对它的独占访问:锈迹禁止这样做。

由于您使用drain()来使用self.func中的所有元素,我建议您在循环之前用一个空的向量交换这个向量,然后在这个不再是self一部分的向量上迭代。此处不涉及向量内容的副本;swap()只处理指针。

下面是您代码的一个过于简化的版本,因此进行了修改。

代码语言:javascript
复制
struct Forth {
    func: Vec<String>,
}

impl Forth {
    fn eval(&mut self) {
        /*
        for item in self.func.drain(..) {
            self.appropriate(&self);
        }
        */
        let mut func = Vec::new();
        std::mem::swap(&mut self.func, &mut func);
        for item in func.drain(..) {
            let b = self.appropriate();
            println!("{:?} {:?}", item, b);
        }
    }

    fn appropriate(&self) -> bool {
        false
    }
}

fn main() {
    let mut f = Forth {
        func: vec!["aaa".into(), "bbb".into()],
    };
    f.eval();
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72763423

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档