处理 Rust 中的未知可变性

问题描述 投票:0回答:1

我无法理解何时使用可变引用而不是特征中的不可变引用。

以下访客实现示例取自

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
实例,为非可变节点创建一个实例。有没有更好的方法来实现这种“可选可变性”?

rust traits mutability
1个回答
0
投票

复制访客是正确的做法。 Rust 无法抽象引用的可变性,并且有很多这样做的例子,即使在 std 中也是如此(例如切片迭代器)。如果这太多了,您可以使用宏来帮助解决。

© www.soinside.com 2019 - 2024. All rights reserved.