处理铁 rust 中未知的突变性

wfypjpf4  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(99)

我很难理解什么时候使用可变引用,而不是traits中的不可变引用。
下面的Visitor实现示例取自Rust Design Patterns

mod visit {
    use ast::*;

    pub trait Visitor<T> {
        fn visit_name(&mut self, n: &Name) -> T;
        fn visit_stmt(&mut self, s: &Stmt) -> T;
        fn visit_expr(&mut self, e: &Expr) -> T;
    }
}

当不需要在遍历AST时修改节点时,此模式工作得很好。但对于某些用例,在遍历时更改节点可能是一个值得做出的设计选择。
书中的解决方案以文件夹模式的形式出现:

mod fold {
    use ast::*;

    pub trait Folder {
        fn fold_name(&mut self, n: Box<Name>) -> Box<Name> { ... }
        fn fold_stmt(&mut self, s: Box<Stmt>) -> Box<Stmt> { ... }
        fn fold_expr(&mut self, e: Box<Expr>) -> Box<Expr> { ... }
    }
}

类似的事情可以通过简单地使每个AST节点可变来实现。
然而,拥有这两种解决方案似乎是乏味的,而不是维护。对于具有许多不同节点的大型AST,存在大量代码重复;必须为可变节点创建一个Visitor示例,为非可变节点创建一个示例。有没有更好的方法来实现这种“可选可变性”?

yb3bgrhw

yb3bgrhw1#

复制访问者是正确的做法。Rust没有办法抽象引用的可变性,并且有很多这样做的例子,即使在std中(例如。切片迭代器)。如果这是太多的样板,你可以使用宏来帮助它。

相关问题