From: Stefan Behnel on
MRAB, 15.07.2010 21:33:
> Stefan Behnel wrote:
>> Karsten Wutzke, 15.07.2010 20:45:
>>> Well, I'm most experienced in OO, so writing OO in Python seems like
>>> the way to start with Python. The visitor pattern uses single-
>>> dispatch, that is, it determines which method to call be the type of
>>> object passed in.
>>
>> Well, then do that. Put the types into a dict and map them to the
>> functions to call, then call the function through the dict. That's a
>> pretty common way to do dispatching.
>>
>>
>>> Note, that I have an hierarchical object structure which I want to
>>> iterate over, so using OO looked natural to me. If there's a better
>>> approach, I'm all ears.
>>
>> You speak in riddles, but my guess is that your problem is that you
>> don't want to dispatch mechanism to match only exact types but also
>> subtypes. No problem, just build your dict incrementally and add new
>> types as they come in. See this file for an example:
>>
>> http://hg.cython.org/cython-devel/file/tip/Cython/Compiler/Visitor.py
>>
> Another variation: the dispatch table starts with entries for certain
> types then it adds subtypes on demand:
>
> def visit(self, obj):
> try:
> handler = self.dispatch_table[type(obj)]
> except KeyError:
> for disp_type, disp_func in self.dispatch_table.items():
> if isinstance(obj, disp_type):
> self.dispatch_table[type(obj)] = disp_func
> handler = disp_func
> else:
> raise RuntimeError("Visitor does not accept object: %s" % obj)
> return handler(obj)

Well, yes, that's basically what the code behind the above link does,
except that it follows the type hierarchy correctly to find the closest match.

Stefan

From: Ian Hobson on
On 15/07/2010 18:58, Karsten Wutzke wrote:
> Hello,
>
> this is obviously a Python OO question:
>
> Since Python isn't stringly typed, single-dispatch isn't available per
> se. So is the "double-dispatch" Visitor pattern, which is usually used
> in OO systems to implement code generators. So, what is the de facto
> method in Python to handle source code generation?
>
> Karsten
>
I'm baffled. Not by what you mean by stringly, but....

What feature of Python stops you writing the three parts of the visitor
pattern:

IIRC you need:

A tree walker that creates the visitor and walks the tree calling
node.visitFrom(visitor)
on each one in the required order.

The visitfrom(aVisitor) routines in each node type that calls
aVisitor.visitedMyNodeType(self)
where MyNodeType is, naturally different for each node type!

All the
def visitedNodeType(aNode): routines in visitor to generate the code.

Simples! No? :)

Ian




From: Ian Hobson on
On 15/07/2010 18:58, Karsten Wutzke wrote:
> Hello,
>
> this is obviously a Python OO question:
>
> Since Python isn't stringly typed, single-dispatch isn't available per
> se. So is the "double-dispatch" Visitor pattern, which is usually used
> in OO systems to implement code generators. So, what is the de facto
> method in Python to handle source code generation?
>
> Karsten
>
I'm baffled. Not by what you mean by stringly, but....

What feature of Python stops you writing the three parts of the visitor
pattern:

IIRC you need:

A tree walker that creates the visitor and walks the tree calling
node.visitFrom(visitor)
on each one in the required order.

The visitfrom(aVisitor) routines in each node type that calls
aVisitor.visitedMyNodeType(self)
where MyNodeType is, naturally different for each node type!

All the
def visitedNodeType(aNode): routines in visitor to generate the code.

Simples! No? :)

Ian




From: Carl Banks on
On Jul 15, 11:45 am, Karsten Wutzke <kwut...(a)web.de> wrote:
> On 15 Jul., 20:28, Thomas Jollans <tho...(a)jollans.com> wrote:
>
> > On 07/15/2010 07:58 PM, Karsten Wutzke wrote:
>
> > > Hello,
>
> > > this is obviously a Python OO question:
>
> > > Since Python isn't stringly typed,
>
> > I expect this is an innocent typo, and you mean strictly.
>
> > > single-dispatch isn't available per se. So is the "double-dispatch" Visitor pattern,
>
> Yes, typo, I meant strictly.
>
>
>
>
>
> > Wait, what?
> > First of all, python is strictly typed in that every object has exactly
> > one type, which is different from other types. So you can't do "1"+2, as
> > you can in some other languages.
>
> > Anyway, this is interesting: Tell me more about how Python's dynamic
> > nature makes it impossible to do whatever you're trying to do. I'm
> > baffled. What are you trying to do, anyway?
>
> > > which is usually used
> > > in OO systems to implement code generators. So, what is the de facto
> > > method in Python to handle source code generation?
>
> > WHOA! Now if that isn't a Gedankensprung. Also, I'm still very far from
> > your train of thought, apparently: Now, the thing that code generators
> > probably share is that they write code to files. It depends on what I'm
> > trying to do of course, but I expect there's a good chance that if I
> > wrote a code generator in Python, it wouldn't be particularly
> > object-oriented at all.
>
> Well, I'm most experienced in OO, so writing OO in Python seems like
> the way to start with Python. The visitor pattern uses single-
> dispatch, that is, it determines which method to call be the type of
> object passed in. I did some reading and it turned out that Python
> can't do it without some tricks (function decorators and 3rd party
> code). For what I'm doing, I can't, or rather don't want to rely on
> 3rd party code (that has reasons). Thus, the visitor OO pattern must
> be replaced by some other way.

Oh brother.

Around these parts, we consider the main use of most Design Patterns
to be to work around limitations of other languages. Visitor Pattern
is probably the worst example of it.

In Python it's completely unnecessary (at least in its boilerplate-
heavy incarnation as used in C++), and the fact that Python isn't
strongly typed, as you put it, is exactly the reason why.

Say you have a bunch of unrelated types that define a calculate
method, you have a variable x that could be any of these types.
Here's how you would do that in Python:

x.calculate()

Bam, that's it. Visitor Pattern in Python. You don't have to create
a bunch of homemade dispatching boilerplate like you do in C++.


Carl Banks
From: Stefan Behnel on
Carl Banks, 16.07.2010 01:14:
> Around these parts, we consider the main use of most Design Patterns
> to be to work around limitations of other languages. Visitor Pattern
> is probably the worst example of it.
>
> In Python it's completely unnecessary (at least in its boilerplate-
> heavy incarnation as used in C++), and the fact that Python isn't
> strongly typed, as you put it, is exactly the reason why.
>
> Say you have a bunch of unrelated types that define a calculate
> method, you have a variable x that could be any of these types.
> Here's how you would do that in Python:
>
> x.calculate()
>
> Bam, that's it. Visitor Pattern in Python. You don't have to create
> a bunch of homemade dispatching boilerplate like you do in C++.

Well, you can do that in every OO language. It's not what the visitor
pattern is there for, though.

The code I referenced is from the Cython compiler, and we use it to "do
stuff" with the AST. The visitor pattern is actually a pretty common way to
bind code in a single place that does a certain thing to different parts of
a data structure. Without it, if you kept that code *inside* of the data
structure, you'd have to spill the type specific parts all over your code.

Stefan