Code generator and visitor pattern

Mick Krippendorf mad.mick at gmx.de
Sat Jul 17 15:55:09 EDT 2010


Hello,

Am 16.07.2010 09:52, Michele Simionato wrote:
> [os.path.walk vs os.walk]
> There is a big conceptual difference between os.path.walk and os.walk.
> The first works like a framework: you pass a function to it and
> os.path.walk is in charging of calling it when needed. The second works
> like a library: os.walk flattens the hierarchical structure and then
> you are in charge of doing everything you wish with it.
> 
> os.walk is the Pythonic way, and you suggested to follow that
> approach; for instance elementTree and lxml (libraries for parsing XML 
> data) work exactly that way. Actually one of the motivating examples for
> the introduction of generators in Python was their use in flattening
> data structure, i.e. exactly the pattern used by os.walk.

The Visitor Pattern isn't about traversing, so they could as well have
had an os.walk() that took a visitor object. Instead, it's about the
untangling of unrelated stuff. Not the traversing vs. everything else -
that's what iterators are for, like you said. But if you want to be able
to add new types of operations without ever touching the code of the
objects on which to apply those operations, then the VP is an easy way
to accomplish things:

<python>

class IfNode:
    def apply(self, operation):
        operation.handleIfNode(self)
...

class ElseNode:
    def apply(self, operation):
        operation.handleElseNode(self)
...

class PrettyPrinter:
    def handleIfNode(self, if_node):
        # print if_node pretty
    def handleElseNode(self, else_node):
        # print else_node pretty
...

class Interpreter:
    def handleIfNode(self, if_node):
        # interpret if_node
    def handleElseNode(self, else_node):
        # interpret else_node
...

class AST:
    def apply(self, operation):
        # apply operation to all nodes
...

some_ast = ...
some_ast.apply(PrettyPrinter())
some_ast.apply(Interpreter())

</python>

The traversing in AST.apply() is not really part of the pattern, it
could also be done in the client code. The VP lives in the relation
between the ...Node and the operation classes. It Encapsulates What
Varies and helps to uphold the Open/Closed Principle, because to add new
operations one does not need to touch the ...Node classes. It implements
double dispatching in a single dispatch language.


Regards,
Mick.



More information about the Python-list mailing list