如何解决错误“一次不能多次借用`*self`作为可变对象”

YNX*_*YNX 4 rust

我是 Rust 新手。这是一段计算机股票交易的代码。该策略将在触发时买入一些股票SignalTrigger,并在 30 岁/90 岁后以不同方式卖出这些股票。代码无法编译。这是代码:

use std::cmp;
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::collections::BinaryHeap;
use std::convert::TryFrom;
use std::error::Error;
use std::fs::File;
use std::io;
use std::process;

#[derive(Debug)]
struct Depth {
    ts: u32,
    ap_vec: Vec<f64>,
    bp_vec: Vec<f64>,
    av_vec: Vec<u32>,
    bv_vec: Vec<u32>,
}


struct Order {
    ts: u32,
    id: u32,
    is_buy: bool,
    is_mkt: bool,
    vol: u32,
    price: f64,
}

struct LongPosition {
    vol_left: u32,
    ts: u32,
}

struct Strategy {
    order_id: u32,
    prev_buy_ts: u32,
    map_orderid_position: BTreeMap<u32, LongPosition>, // map<order_id, volume_left>
}

impl Strategy {
    fn on_depth(&mut self, depth: &Depth) -> Vec<Order> {
        let mut orders_vec: Vec<Order> = Vec::new();
        for (order_id, long_position) in &mut self.map_orderid_position {
            if depth.ts - long_position.ts > 90 * 1000 {
                let order = self.make_order(depth.ts, false, true, long_position.vol_left, 0.0);
                orders_vec.push(order);
            } else if depth.ts - long_position.ts > 60 * 1000 {
                let order = self.make_order(depth.ts,false,true,long_position.vol_left,depth.bp_vec[0]);
                orders_vec.push(order);
            }
        }
        return orders_vec;
    }

    fn make_order(&mut self, ts: u32, is_buy: bool, is_mkt: bool, vol: u32, price: f64) -> Order {
        let order = Order {
            id: self.order_id,
            ts,
            is_buy,
            is_mkt,
            vol,
            price,
        };
        self.order_id = self.order_id + 1;
        return order;
    }
}

fn main() {
    let empty_price_vec: Vec<f64> = Vec::new();
    let map_orderid_position: BTreeMap<u32, LongPosition> = BTreeMap::new();
    let mut strategy = Strategy {
        prev_buy_ts: 0,
        order_id: 0,
        map_orderid_position: map_orderid_position,
    };
}

Run Code Online (Sandbox Code Playgroud)

编译说:(我在代码片段中注释了第 88 行和第 90 行)

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src\main.rs:46:29
   |
44 |         for (order_id, long_position) in &mut self.map_orderid_position {
   |                                          ------------------------------
   |                                          |
   |                                          first mutable borrow occurs here
   |                                          first borrow later used here
45 |             if depth.ts - long_position.ts > 90 * 1000 {
46 |                 let order = self.make_order(depth.ts, false, true, long_position.vol_left, 0.0);
   |                             ^^^^ second mutable borrow occurs here

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src\main.rs:49:29
   |
44 |         for (order_id, long_position) in &mut self.map_orderid_position {
   |                                          ------------------------------
   |                                          |
   |                                          first mutable borrow occurs here
   |                                          first borrow later used here
...
49 |                 let order = self.make_order(depth.ts,false,true,long_position.vol_left,depth.bp_vec[0]);
   |                             ^^^^ second mutable borrow occurs here

error: aborting due to 2 previous errors; 12 warnings emitted

For more information about this error, try `rustc --explain E0499`.
error: could not compile `greeting`
Run Code Online (Sandbox Code Playgroud)

我对 Rust 有点困惑,像这样的片段在其他语言中确实很常见。您能解释一下并告诉我如何解决(避免)这种情况吗?

Gur*_*ngh 8

当您调用时,您正在借用整个实例self.make_order。编译器无法确定您不会进行更改map_orderid_position。相反,您可以创建一个独立函数并将对字段的可变引用传递给order_id它。

impl Strategy {
    fn on_depth(&mut self, depth: &Depth) -> Vec<Order> {
        let mut orders_vec: Vec<Order> = Vec::new();
        for (order_id, long_position) in &mut self.map_orderid_position {
            if depth.ts - long_position.ts > 90 * 1000 {
                let order = make_order(depth.ts, false, true, long_position.vol_left, 0.0, &mut self.order_id);
                orders_vec.push(order);
            } else if depth.ts - long_position.ts > 60 * 1000 {
                let order = make_order(depth.ts,false,true,long_position.vol_left,depth.bp_vec[0], &mut self.order_id);
                orders_vec.push(order);
            }
        }
        return orders_vec;
    }

    
}

fn make_order(ts: u32, is_buy: bool, is_mkt: bool, vol: u32, price: f64, order_id: &mut u32) -> Order {
    let order = Order {
        id: *order_id,
        ts,
        is_buy,
        is_mkt,
        vol,
        price,
    };
    *order_id += 1;
    return order;
}
Run Code Online (Sandbox Code Playgroud)