Rust 与内部易变性作斗争

Rust 与内部易变性作斗争,rust,borrow-checker,mutability,Rust,Borrow Checker,Mutability,我的数据结构如下: struct R { hmhs: HashMap<i64, HashSet<i64>>, } impl R { fn hs_for_hmhs(&mut self) -> &mut HashSet<i64> { if let None = self.hmhs.get(&0) { self.hmhs.insert(0, HashSet::new());

我的数据结构如下:

struct R {
    hmhs: HashMap<i64, HashSet<i64>>,
}

impl R {
    fn hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
        if let None = self.hmhs.get(&0) {
            self.hmhs.insert(0, HashSet::new());
        }

        self.hmhs.get_mut(&0).unwrap()
    }

    fn iter_for_hmhs<'a>(&'a mut self) -> impl Iterator<Item = &'a i64> {
        self.hs_for_hmhs().iter()
    }

    fn insert_for_hmhs(&mut self, i: i64) -> bool {
        self.hs_for_hmhs().insert(i)
    }
}
然而,我似乎总是遇到问题。主要是各种各样的

我在这里尝试了很多变体,但我遗漏了一些东西 我的理解是基本的。有没有一种方法可以实现我想要的 想要什么

:

使用std::cell::RefCell;
使用std::collections::{HashMap,HashSet};
结构R{
hmhs:HashMap,
}
impl R{
fn hs_for_hmhs(&mut self)->&mut HashSet{
如果let None=self.hmhs.get(&0){
self.hmhs.insert(0,HashSet::new());
}
self.hmhs.get_mut(&0).unwrap()
}
fn iter_for_hmhs impl Iterator我找到了一个解决方案——提取
HashMap
作为原始指针。这反过来意味着我可以访问
HashSet
,而无需使用包括返回迭代器在内的诡计

作为一个解决方案,我很高兴。不安全的代码很小并且包含在内,如果我理解编译器抱怨不安全的原因,它就不会出现在这段代码中,因为在构建之后,
HashMap
HashSet
都不会被删除或替换

这是很大的努力

use std::cell::RefCell;
use std::collections::{HashMap, HashSet};

struct R {
    hmhs: HashMap<i64, HashSet<i64>>,
}

impl R {
    fn hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
        if let None = self.hmhs.get(&0) {
            self.hmhs.insert(0, HashSet::new());
        }

        self.hmhs.get_mut(&0).unwrap()
    }

    fn iter_for_hmhs<'a>(&'a mut self) -> impl Iterator<Item = &'a i64> {
        self.hs_for_hmhs().iter()
    }

    fn insert_for_hmhs(&mut self, i: i64) -> bool {
        self.hs_for_hmhs().insert(i)
    }
}

struct S {
    hmhs: RefCell<HashMap<i64, HashSet<i64>>>,
}

impl S {
    fn hs_as_ptr(&self) -> *mut HashMap<i64, HashSet<i64>> {
        self.hmhs.borrow_mut().entry(0).or_insert(HashSet::new());
        self.hmhs.as_ptr()
    }

    fn mut_hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
        unsafe { (*self.hs_as_ptr()).get_mut(&0).unwrap() }
    }
    fn hs_for_hmhs(&self) -> &HashSet<i64> {
        unsafe { (*self.hs_as_ptr()).get(&0).unwrap() }
    }

    fn iter_for_hmhs<'a>(&'a self) -> impl Iterator<Item = &'a i64> + 'a {
        self.hs_for_hmhs().iter()
    }

    fn insert_for_hmhs(&mut self, i: i64) -> bool {
        self.mut_hs_for_hmhs().insert(i)
    }
}

fn main() {
    let mut r = R {
        hmhs: HashMap::new(),
    };
    let mut s = S {
        hmhs: RefCell::new(HashMap::new()),
    };

    r.insert_for_hmhs(10);
    s.insert_for_hmhs(20);

    println!("r next: {:?}", r.iter_for_hmhs().next());
    println!("s next: {:?}", s.iter_for_hmhs().next());
}
使用std::cell::RefCell;
使用std::collections::{HashMap,HashSet};
结构R{
hmhs:HashMap,
}
impl R{
fn hs_for_hmhs(&mut self)->&mut HashSet{
如果let None=self.hmhs.get(&0){
self.hmhs.insert(0,HashSet::new());
}
self.hmhs.get_mut(&0).unwrap()
}
fn iter_for_hmhs impl Iterator(&'a self)->impl Iterator bool{
self.mut_hs_for_hmhs().insert(i)
}
}
fn main(){
设mut r=r{
hmhs:HashMap::new(),
};
设mut s=s{
hmhs:RefCell::new(HashMap::new()),
};
r、 为_-hmhs(10)插入_;
s、 为_-hmhs插入_(20);
println!(“r next:{:?}”,r.iter_代表_hmhs().next());
println!((“s next:{:?}”,s.iter_代表_hmhs().next());
}

为什么需要可变地借用它?所有的方法都会返回对其内容的不可变引用?这是什么呢?
HashMap
和第二个
borrow\u mut
调用。我不知道。如果我不这样做,它会抱怨更多。啊,我没有注意到
insert\u for_hmhs
调用
insert
。哦,
HashSet
--是的,这是一个问题part将实现结构的公共接口。HashMap实际上是一个实现细节。这是一个棘手的问题,我想知道您是否应该尝试另一种方法。例如,它将让您半途而废—一个指向
HashSet
的抽象智能指针。但很难返回迭代器。
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};

struct R {
    hmhs: HashMap<i64, HashSet<i64>>,
}

impl R {
    fn hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
        if let None = self.hmhs.get(&0) {
            self.hmhs.insert(0, HashSet::new());
        }

        self.hmhs.get_mut(&0).unwrap()
    }

    fn iter_for_hmhs<'a>(&'a mut self) -> impl Iterator<Item = &'a i64> {
        self.hs_for_hmhs().iter()
    }

    fn insert_for_hmhs(&mut self, i: i64) -> bool {
        self.hs_for_hmhs().insert(i)
    }
}

struct S {
    hmhs: RefCell<HashMap<i64, HashSet<i64>>>,
}

impl S {
    fn hs_for_hmhs(&self) -> &mut HashSet<i64> {
        if let None = self.hmhs.borrow().get(&0) {
            self.hmhs.borrow_mut().insert(0, HashSet::new());
        }

        self.hmhs.borrow_mut().get_mut(&0).unwrap()
    }

    fn iter_for_hmhs(&self) -> impl Iterator<Item = &i64> {
        self.hs_for_hmhs().iter()
    }

    fn insert_for_hmhs(&self, i: i64) -> bool {
        self.hs_for_hmhs().insert(i)
    }
}

fn main() {}
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};

struct R {
    hmhs: HashMap<i64, HashSet<i64>>,
}

impl R {
    fn hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
        if let None = self.hmhs.get(&0) {
            self.hmhs.insert(0, HashSet::new());
        }

        self.hmhs.get_mut(&0).unwrap()
    }

    fn iter_for_hmhs<'a>(&'a mut self) -> impl Iterator<Item = &'a i64> {
        self.hs_for_hmhs().iter()
    }

    fn insert_for_hmhs(&mut self, i: i64) -> bool {
        self.hs_for_hmhs().insert(i)
    }
}

struct S {
    hmhs: RefCell<HashMap<i64, HashSet<i64>>>,
}

impl S {
    fn hs_as_ptr(&self) -> *mut HashMap<i64, HashSet<i64>> {
        self.hmhs.borrow_mut().entry(0).or_insert(HashSet::new());
        self.hmhs.as_ptr()
    }

    fn mut_hs_for_hmhs(&mut self) -> &mut HashSet<i64> {
        unsafe { (*self.hs_as_ptr()).get_mut(&0).unwrap() }
    }
    fn hs_for_hmhs(&self) -> &HashSet<i64> {
        unsafe { (*self.hs_as_ptr()).get(&0).unwrap() }
    }

    fn iter_for_hmhs<'a>(&'a self) -> impl Iterator<Item = &'a i64> + 'a {
        self.hs_for_hmhs().iter()
    }

    fn insert_for_hmhs(&mut self, i: i64) -> bool {
        self.mut_hs_for_hmhs().insert(i)
    }
}

fn main() {
    let mut r = R {
        hmhs: HashMap::new(),
    };
    let mut s = S {
        hmhs: RefCell::new(HashMap::new()),
    };

    r.insert_for_hmhs(10);
    s.insert_for_hmhs(20);

    println!("r next: {:?}", r.iter_for_hmhs().next());
    println!("s next: {:?}", s.iter_for_hmhs().next());
}