Я видел шаблон Visitor, используемый для прогулки по AST .Чтобы использовать этот шаблон, вы добавляете метод accept(visitor)
для объектов узла AST.Этот метод вызывает visitor.visit(self)
, который, в свою очередь, «обрабатывает» узел для получения желаемого результата (например, довольно печатная версия AST).
Обратите внимание, что обычно вам нужно изменить узлысами добавить метод.Но что делать, если ваш AST использует встроенные объекты.Библиотека Ruby Ripper возвращает AST в виде массива массивов.Я мог бы добавить метод accept
следующим образом:
class Array
def accept(visitor)
visitor.visit(self)
end
end
Глядя на документацию для массива , в настоящее время нет метода accept
, поэтому конфликта не будет,Но мне это не совсем подходит, особенно если я сам пишу библиотеку.Я бы не хотел «загрязнять» встроенный объект, на который могли бы полагаться другие.
Однако это не уникально для Ruby, так как я мог бы добавить метод расширения в C #, чтобы сделать подобноевещь.
Мой вопрос таков: должен ли я использовать шаблон Visitor в этом сценарии или я должен написать рекурсивную функцию, которая просто принимает тип данных, над которым я работаю, и возвращает ответ, который я хочу?