【问题标题】:Rust functions behave weirdlyRust 函数行为异常
【发布时间】:2022-12-04 04:28:58
【问题描述】:

我有一个如下所示的实现:

use crate::queue::{Task, WorkQueue};
use digest::consts::U32;
use digest::generic_array::typenum::Pow;
use sha2::digest::generic_array::GenericArray;
use sha2::{Digest, Sha256};
use std::fmt::Write;
use std::ops::Add;
use std::sync;

pub type Hash = GenericArray<u8, U32>;

#[derive(Debug, Clone)]
pub struct Block {
    pub prev_hash: Hash,
    pub generation: u64,
    pub difficulty: u8,
    pub data: String,
    pub proof: Option<u64>,
}

impl Block {
pub fn mine_range(self: &Block, workers: usize, start: u64, end: u64, chunks: u64) -> u64 {
        // TODO: with `workers` threads, check proof values in the given range, breaking up
    // into `chunks` tasks in a work queue. Return the first valid proof found.
        // HINTS:
        // - Create and use a queue::WorkQueue.
        // - Use sync::Arc to wrap a clone of self for sharing.
        unimplemented!()
    }

    pub fn mine_for_proof(self: &Block, workers: usize) -> u64 {
        let range_start: u64 = 0;
        let range_end: u64 = 8 * (1 << self.difficulty); // 8 * 2^(bits that must be zero)
        let chunks: u64 = 2345;
        self.mine_range(workers, range_start, range_end, chunks)
    }

    pub fn mine(self: &mut Block, workers: usize) {
        self.proof = Some(self.mine_for_proof(workers));
    }
}

struct MiningTask {
    block: sync::Arc<Block>,
    // TODO: more fields as needed
    workers: usize
}

impl Task for MiningTask {
    type Output = u64;

    fn run(&self) -> Option<u64> {
        // TODO: what does it mean to .run?
        self.block.mine(self.workers);
        let result = self.block.proof;
        return result;
    }
}

现在,如果我像这样从运行中取出返回状态:

impl Task for MiningTask {
    type Output = u64;

    fn run(&self) -> Option<u64> {
        // TODO: what does it mean to .run?
        self.block.mine(self.workers);
        let result = self.block.proof;
        //return result;
    }
}

没有借用错误但是像这样:

impl Task for MiningTask {
    type Output = u64;

    fn run(&self) -> Option<u64> {
        // TODO: what does it mean to .run?
        self.block.mine(self.workers);
        let result = self.block.proof;
        return result;
    }
}

它给了我: 不能借用 Arc 中的数据作为可变数据 trait DerefMut需要通过dereference修改,Arc&lt;Block&gt;没有实现

我不明白为什么归还东西会导致借用,我该如何解决?最好没有 Mutex 库或没有借用?即使我尝试克隆自我它仍然执行借用,我很困惑。

【问题讨论】:

    标签: rust


    【解决方案1】:

    在 MiningTask::run 方法中,您试图返回 Block 结构的证明字段。该字段存储在 Option 类型中,这意味着它要么是包含证明的 Some 值,要么是 None 值(如果尚未找到)。

    当您尝试返回此值时,编译器无法推断您是要返回对证明字段的引用还是证明值的副本。为了返回对证明字段的引用,您需要使用 Option::as_ref 方法将 Option 类型转换为引用的 Option。例如:

    fn run(&self) -> Option<&u64> {
        self.block.mine(self.workers);
        let result = self.block.proof.as_ref();
        return result;
    }
    

    或者,您可以通过使用 Option::copied 方法将 Option 类型转换为基础类型(在本例中为 u64)的 Option 来返回证明值的副本。例如:

    fn run(&self) -> Option<u64> {
        self.block.mine(self.workers);
        let result = self.block.proof.copied();
        return result;
    }
    

    在您提供的代码中,您已经完全删除了 return 语句。这意味着 MiningTask::run 方法将始终返回 None,因为返回类型是 Option 并且方法主体中没有 return 语句。这不会导致借用错误,因为 Block 结构被包装在 Arc 中,允许对相同数据的多个引用。

    但是,以这种方式删除 return 语句意味着 run 方法将不会返回 mine 方法找到的证明值。这可能不是您想要的行为,具体取决于您尝试对 MiningTask 结构执行的操作。

    【讨论】:

      猜你喜欢
      • 2011-10-18
      • 1970-01-01
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      • 1970-01-01
      • 2021-07-18
      相关资源
      最近更新 更多