我已经看到了用于遍历AST的访问者模式。accept(visitor)
要使用此模式,您需要在 AST 节点对象上添加一个方法。这个方法调用visitor.visit(self)
它,反过来,“处理”节点以获得所需的结果(例如,AST 的漂亮打印版本)。
请注意,您通常必须修改节点本身才能添加方法。但是,如果您的 AST 使用内置对象怎么办。Ruby 的 Ripper 库将 AST 作为数组返回。我可以添加accept
如下方法:
class Array
def accept(visitor)
visitor.visit(self)
end
end
查看 Array的文档,目前没有accept
方法,所以不会有冲突。但是,这对我来说并不完全正确,尤其是当我自己编写一个库时。我不想“污染”其他人可能依赖的内置对象。
不过,这并不是 Ruby 独有的,因为我可以在 C# 中添加一个扩展方法来做类似的事情。
我的问题是:我应该在这种情况下使用访问者模式,还是应该编写一个递归函数,只接受我正在处理的数据类型并返回我想要的答案?