This is a discussion on Traversing Composites with Visitors within the Software Patterns forums, part of the Testing category; Hi, I'm trying to make head or tail of this and failing miserably! I have a simple component/composite-...
|
|||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
|
|||
|
Traversing Composites with Visitors
Hi,
I'm trying to make head or tail of this and failing miserably! I have a simple component/composite-leaf structure which just store names. I'd like to print it like a directory in the format below but I can't figure it out. People keep talking about recursion with depth values but the visit calls aren't recursive so I haven't a clue. So far with simple printfs I get the following: A B C D E but I'd like A +-B | +-C | +-D +-E HELP! Many Thanks Tony |
|
|||
|
Re: Traversing Composites with Visitors
On Sat, 11 Oct 2003 15:07:47 +0200, Anthony Webster wrote:
> but I'd like > > A > +-B > | +-C > | +-D > +-E > > HELP! Something like this (Ruby-example in the bottom of this mail) server> ruby vis.rb +-A +-B | +-C | +-E | | +-D | | +-F | | +-G | +-H +-I server> The trick is to determine whether or not you are dealing with the last child, if not then you use '|' otherwise use space. -- Simon Strandgaard class Leaf def initialize(name) @name = name end attr_reader :name def accept(visitor) visitor.visit_leaf self end end class Composite def initialize(name, *children) @name = name @children = children end attr_reader :children, :name def accept(visitor) visitor.visit_composite self end end class Visitor def initialize @result = [] @last = true end attr_reader :result def visit_leaf(i) @result << "+-" + i.name end def visit_composite(i) pad = @last ? " " : "|" i.children[0..-2].each {|child| @last = false child.accept self } @last = true i.children.last.accept self @result.map!{|s| pad + " " + s } @result.unshift "+-" + i.name end end data = Composite.new('A', Composite.new('B', Composite.new('C', Leaf.new('D'), Composite.new('E', Leaf.new('F'), Leaf.new('G') ), Leaf.new('H') ) ), Leaf.new('I') ) v = Visitor.new data.accept v puts v.result |
|
|||
|
Re: Traversing Composites with Visitors
On Sat, 11 Oct 2003 17:23:16 +0200, Simon Strandgaard wrote:
> On Sat, 11 Oct 2003 15:07:47 +0200, Anthony Webster wrote: >> but I'd like >> >> A >> +-B >> | +-C >> | +-D >> +-E >> >> HELP! > > > Something like this (Ruby-example in the bottom of this mail) > > server> ruby vis.rb > +-A > +-B > | +-C > | +-E > | | +-D > | | +-F > | | +-G > | +-H > +-I > server> Argh.. too quick.. now its outputs correct ;-) server> ruby vis.rb +-A +-B | +-C | +-D | +-E | | +-F | | +-G | +-H +-I server> class Leaf def initialize(name) @name = name end attr_reader :name def accept(visitor) visitor.visit_leaf self end end class Composite def initialize(name, *children) @name = name @children = children end attr_reader :children, :name def accept(visitor) visitor.visit_composite self end end class Visitor def initialize @last = true end def visit_leaf(i) ["+-" + i.name] end def visit_composite(i) pad = @last ? " " : "|" res = [] i.children[0..-2].each{|child| @last = false res += child.accept(self) } @last = true res += i.children.last.accept(self) res.map!{|s| pad + " " + s } res.unshift "+-" + i.name res end end data = Composite.new('A', Composite.new('B', Composite.new('C', Leaf.new('D'), Composite.new('E', Leaf.new('F'), Leaf.new('G') ), Leaf.new('H') ) ), Leaf.new('I') ) puts data.accept(Visitor.new) |