有几次,我遇到了一种场景,即可变引用和不可变引用都需要访问器方法.

对于大约3行代码,复制逻辑不是问题,但是当逻辑变得更复杂时,复制粘贴大块代码是不好的.

我希望能够重复使用这两个代码.

Rust是否提供了比复制粘贴代码或使用unsafe次强制转换更好的处理方法?

例如.:

impl MyStruct {
    pub fn get_foo(&self) -> &Bar {
        // ~20 lines of code
        // --- snip ---
        return bar;
    }
    pub fn get_foo_mut(&mut self) -> &mut Bar {
        // ~20 lines of code
        // (exactly matching previous code except `bar` is mutable)
        // --- snip ---
        return bar;
    }
}

下面是一个代码库的更详细摘录,其中一个不可变返回参数被转换为mutable,以支持函数的不可变和可变版本.这使用了包装指针类型(ConstPMutP表示不可变和可变引用),但函数的逻辑应该是明确的.

pub fn face_vert_share_loop<V, F>(f: F, v: V) -> LoopConstP
    where V: Into<VertConstP>,
          F: Into<FaceConstP>
{
    into_expand!(f, v);

    let l_first = f.l_first.as_const();
    let mut l_iter = l_first;
    loop {
        if l_iter.v == v {
            return l_iter;
        }

        l_iter = l_iter.next.as_const();
        if l_iter == l_first {
            break;
        }
    }

    return null_const();
}
pub fn face_vert_share_loop_mut(f: FaceMutP, v: VertMutP) -> LoopMutP {
    let l = face_vert_share_loop(f, v);
    return unsafe {
        // Evil! but what are the alternatives?
        // Perform an unsafe `const` to `mut` cast :(
        // While in general this should be avoided,
        // its 'OK' in this case since input is also mutable.
        l.as_mut()
    };
}

推荐答案

你真的不知道.回想一下,T&T&mut T都是different types.在这种情况下,您的问题与询问"如何避免为StringHashMap编写重复的访问器函数"相同.

Matthieu M有正确的术语"易变性之上的抽象":

TL;DR.表示,Rust可能需要通过新功能增强以支持这一点.由于没有人成功,因此没有人higher kinded types%确定这些功能需要具备哪些功能.目前的最佳猜测是higher kinded types(HKT).

Rust相关问答推荐

在‘await’点上使用‘std::同步::Mutex’是否总是会导致僵局?

使用nom将任何空白、制表符、白线等序列替换为单个空白

阻止websocket中断的中断中断的终端(操作系统错误4)

程序退出后只写入指定管道的数据

如何使用字符串迭代器执行查找?

在函数内定义impl和在函数外定义impl的区别

我如何在Rust中使用传递依赖中的特征?

当rust中不存在文件或目录时,std::FS::File::Create().unwire()会抛出错误

无法从流中读取Redis请求

Gtk4-rs:将监视器作为gdk::monitor获取,而不是作为glib::对象获取

在IntoIter上调用.by_ref().Take().rev()时会发生什么情况

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

在什么情况下 `..._or()` 比 `..._or_else(|| {})` 更好,为什么?

可以在旋转循环中调用try_recv()吗?

Rust: 目标成员属于哪个"目标家族"的列表是否存在?

在不安全的 Rust 中存储对 struct 内部数据的静态引用是否合法?

如何递归传递闭包作为参数?

Rustlings 切片原语

TcpStream::connect - 匹配武器具有不兼容的类型

在 Rust 中退出进程