Prev: Q for Emacs users: code-folding (hideshow)
Next: Best Pythonic Approach to Annotation/Metadata?
From: Thomas Jollans on 16 Jul 2010 13:20 On 07/16/2010 11:00 AM, Jean-Michel Pichavant wrote: > Karsten Wutzke wrote: >>> Yes, typo, I meant strictly. >>> >>> >> >> Damn, I mean strongly. At least not for identifying which methods to >> call depending on the type/s. >> >> Karsten >> > Stringly is the perfect combination of strictly and strongly. Nice one :) stringly typed sounds like "everything is a string" - doesn't Tcl do that ? ^^
From: Mick Krippendorf on 17 Jul 2010 15:38 Karsten Wutzke wrote: > The visitor pattern uses single-dispatch, that is, it determines > which method to call be the type of object passed in. Say, in Python, I have an object o and want to call one of it's methods, say m. Then which of possibly many methods m to call is determined by the type of o, and nothing else (at least without further magic) - hence, it is single dispatch. The VP uses two single dispatch calls (one being a callback) to accomplish double dispatching. Java has a form of multiple dispatch through function overloading. In fact, it's still single dispatch, because which of the targets overloaded methods gets called is determined at compile time by the staticly known types of the methods parameters, AKA the formal parameter types. Anyway. Although VP *uses* double dispatch, it does not necessarily rely on function overloading. In Java the VP is most often implemented like this: <java> interface IASTNode { void accept(IASTVisitor); } class IfNode implements IASTNode { void accept(IASTVisitor visitor) { visitor.visit(this); } } class ElseNode implements IASTNode { void accept(IASTVisitor visitor) { visitor.visit(this); } } interface IASTVisitor { void visit(IfNode node); void visit(ElseNode node); ... } class PrettyPrinter implements IASTVisitor { public void visit(IfNode n) { ... } public void visit(ElseNode n) { ... } } </java> but it could as well be implemented like this: <java> interface IASTNode { void accept(IASTVisitor); } class IfNode implements IASTNode { void accept(IASTVisitor visitor) { visitor.visitIfNode(this); } } class ElseNode implements IASTNode { void accept(IASTVisitor visitor) { visitor.visitElseNode(this); } } interface IASTVisitor { void visitIfNode(IfNode node); void visitElseNode(ElseNode node); ... } class PrettyPrinter implements IASTVisitor { public void visitIfNode(IfNode n) { ... } public void visitElseNode(ElseNode n) { ... } } </java> If Java were *really* a multiple dispatch language, it wouldn't be necessary to repeat the accept-code for every subclass. Instead a single accept method in the base class would suffice. In fact, with true multiple dispatch VP wouldn't even be needed. Regards, Mick.
From: Mick Krippendorf on 17 Jul 2010 15:55 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.
From: Mark Lawrence on 17 Jul 2010 19:08 On 17/07/2010 20:38, Mick Krippendorf wrote: > Karsten Wutzke wrote: >> The visitor pattern uses single-dispatch, that is, it determines >> which method to call be the type of object passed in. > > Say, in Python, I have an object o and want to call one of it's methods, > say m. Then which of possibly many methods m to call is determined by > the type of o, and nothing else (at least without further magic) - > hence, it is single dispatch. The VP uses two single dispatch calls (one > being a callback) to accomplish double dispatching. > > Java has a form of multiple dispatch through function overloading. In > fact, it's still single dispatch, because which of the targets > overloaded methods gets called is determined at compile time by the > staticly known types of the methods parameters, AKA the formal parameter > types. > > Anyway. Although VP *uses* double dispatch, it does not necessarily rely > on function overloading. In Java the VP is most often implemented like this: > > <java> > > interface IASTNode { > void accept(IASTVisitor); > } > > class IfNode implements IASTNode { > void accept(IASTVisitor visitor) { > visitor.visit(this); > } > } > > class ElseNode implements IASTNode { > void accept(IASTVisitor visitor) { > visitor.visit(this); > } > } > > interface IASTVisitor { > void visit(IfNode node); > void visit(ElseNode node); > ... > } > class PrettyPrinter implements IASTVisitor { > public void visit(IfNode n) { > ... > } > public void visit(ElseNode n) { > ... > } > } > > </java> > > but it could as well be implemented like this: > > <java> > > interface IASTNode { > void accept(IASTVisitor); > } > > class IfNode implements IASTNode { > void accept(IASTVisitor visitor) { > visitor.visitIfNode(this); > } > } > > class ElseNode implements IASTNode { > void accept(IASTVisitor visitor) { > visitor.visitElseNode(this); > } > } > > interface IASTVisitor { > void visitIfNode(IfNode node); > void visitElseNode(ElseNode node); > ... > } > class PrettyPrinter implements IASTVisitor { > public void visitIfNode(IfNode n) { > ... > } > public void visitElseNode(ElseNode n) { > ... > } > } > > </java> > > If Java were *really* a multiple dispatch language, it wouldn't be > necessary to repeat the accept-code for every subclass. Instead a single > accept method in the base class would suffice. In fact, with true > multiple dispatch VP wouldn't even be needed. > > > Regards, > Mick. Boilerplate, boilerplate everywhere, but not a beer to drink. Hope everyone at EuroPython is having a good time. Kindest regards. Mark Lawrence.
From: Mick Krippendorf on 18 Jul 2010 04:09 Mark Lawrence wrote: > On 17/07/2010 20:38, Mick Krippendorf wrote: >> >> If Java were *really* a multiple dispatch language, it wouldn't be >> necessary to repeat the accept-code for every subclass. Instead a single >> accept method in the base class would suffice. In fact, with true >> multiple dispatch VP wouldn't even be needed. > > Boilerplate, boilerplate everywhere, but not a beer to drink. That's Java for ya. <python> class ASTNode: def accept(self, visitor): getattr(visitor, self.__class__.__name__)(self) class IfNode(ASTNode): ... # inherits generic accept method class ElseNode(ASTNode): ... # inherits generic accept method class PrettyPrinter: def IfNode(self, node): ... def ElseNode(self, node): ... </python> Regards, Mick.
First
|
Prev
|
Pages: 1 2 3 4 5 Prev: Q for Emacs users: code-folding (hideshow) Next: Best Pythonic Approach to Annotation/Metadata? |