[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Avoiding if requires type mutation -- evil.rb?

Mikael Brockman

12/12/2004 3:17:00 AM

I am writing a tree editor. The algorithm for displaying a node is
recursive. On leaf nodes, it's trivial. Branches need to display all
their kids.

I would like to implement this with three classes: the Leaf, the
Branch, and the Node. Leaf & Branch are subclasses of Node.

The problem: nodes are mutable. You can add a kid to a node. If that
node's a Leaf, it needs to become a Branch.

I can think of three solutions.

- Add a wrapper object around every Node, and give it a #replace
method.

- Use Object#become from evil.rb.

- Represent nodes and leaves as instances of the same class, and use if
statements.

I'd like #2 the best if evil.pb wasn't likely to win awards for being
the nastiest hack of all time. (Props to the authors!) I don't like #1
or #3, but if I had to choose, I'd go with #3.

Making nodes non-mutable would be annoying and unintuitive, I think.

What would you do?



5 Answers

dblack

12/12/2004 3:31:00 AM

0

dblack

12/12/2004 3:41:00 AM

0

Mikael Brockman

12/12/2004 3:53:00 AM

0

"David A. Black" <dblack@wobblini.net> writes:

> Hi --
>
> On Sun, 12 Dec 2004, Mikael Brockman wrote:
>
> > I am writing a tree editor. The algorithm for displaying a node is
> > recursive. On leaf nodes, it's trivial. Branches need to display all
> > their kids.
> >
> > I would like to implement this with three classes: the Leaf, the
> > Branch, and the Node. Leaf & Branch are subclasses of Node.
> >
> > The problem: nodes are mutable. You can add a kid to a node. If that
> > node's a Leaf, it needs to become a Branch.
> >
> > ...
> >
> > What would you do?
>
> One possibility would be have a Branchlike module and extend leaf
> objects with it when they became branches:
>
> module Branchlike
> def show_kids
> ...
> end
> # etc.
> end
>
> class Branch
> include Branchlike
> # etc.
> end
>
> class Leaf
> def add_node
> extend(Branchlike)
> end
> # etc.
>
> or something along those lines, maybe even more modularized.

Hm. Yes, that could work. The only issue I can see with it regards
removing kids: I'd have to keep extending Branchlike and Leaflike, which
would make leaf.is_a? Branchlike true. I'll probably never use #is_a?,
though.

The proxy thing is kinda starting to grow on me though. It's so simple.
Node#become would be easy to make. I think I prefer that.



Robert Klemme

12/12/2004 11:35:00 AM

0


"Mikael Brockman" <mikael@phubuh.org> schrieb im Newsbeitrag
news:87hdmscik0.fsf@igloo.phubuh.org...
>I am writing a tree editor. The algorithm for displaying a node is
> recursive. On leaf nodes, it's trivial. Branches need to display all
> their kids.
>
> I would like to implement this with three classes: the Leaf, the
> Branch, and the Node. Leaf & Branch are subclasses of Node.
>
> The problem: nodes are mutable. You can add a kid to a node. If that
> node's a Leaf, it needs to become a Branch.
>
> I can think of three solutions.
>
> - Add a wrapper object around every Node, and give it a #replace
> method.
>
> - Use Object#become from evil.rb.
>
> - Represent nodes and leaves as instances of the same class, and use if
> statements.
>
> I'd like #2 the best if evil.pb wasn't likely to win awards for being
> the nastiest hack of all time. (Props to the authors!) I don't like #1
> or #3, but if I had to choose, I'd go with #3.
>
> Making nodes non-mutable would be annoying and unintuitive, I think.
>
> What would you do?

I would not necessarily change the type of the instance. Instead I had just
class Node and would use strategy / state pattern. Using extend with a
Module (like David suggested) is one way to accomplish this, but it becomes
complitcated if the Branch should become a Leaf again. You could instead
keep an instance around that implements all behavior that depends on the
state 'leaf' vs. 'branch'.

Example:


require 'singleton'

class Node
class Leaf
include Singleton

def leaf?() true end
def each(owner) end
end

class Branch
include Singleton

def leaf?() false end
def each(owner,&b) owner.children.each(&b) end
end

attr_reader :children

def initialize
@children = []
@state = Leaf.instance
end

def leaf?() @state.leaf? end
def branch?() ! leaf? end

def each(&b) @state.each(self,&b) end

def add(node)
@children << node
@state = Branch.instance
end

def remove(node)
@children.delete node
@state = Leaf.instance if @children.empty?
end
end


Kind regards

robert

Assaph Mehr

12/13/2004 1:20:00 AM

0

Why make the distinction between leaf and node? A leaf is just a node
without children.

Why not simply have something like (code written to email, not
checked):

class Node
attr_accessor :children

def initialize
children = []
end

def leaf? children.size.zero? end
end

And use it as

if node.leaf?
# do leafy stuff
else
# do branchy stuff
end