
- Forum
- Testing
- Software Patterns
- Traversing Composites with Visitors
Traversing Composites with Visitors
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-leaf structure which ...
-
10-11-2003, 09:07 AM #1Anthony Webster Guest
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
-
10-11-2003, 11:23 AM #2Simon Strandgaard Guest
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
-
10-11-2003, 11:44 AM #3Simon Strandgaard Guest
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)
-
Sponsored Ads

Reply With Quote





