mixin classes (continuning from the last post)

H

hurcan solter

Although I am a seasoned C/C++ programmer(+10 years), I am relatively
new to the ruby (about 2 days) despite having some reservations(ruby
debugger should be theslowest thing in the world) i am otherwise very
impressed with the language, I intend to use Ruby for some code
generation task ,Everything was going well until i hit that roadblock

class REXML::Element
include TSort
def initialize
@dependencies=[]
end
def tsort_each_node(&block)
@elements.each(&block)
end
def tsort_each_child(node, &block)
@dependencies.each(&block) if @dependencies.size>0
end
end
well as you can see, i need to topologically sort some nodes in an
xml file and there was a module Tsort in the
ruby. from what understand i need to extend to class REXML::Element
to feed Tsort algorithm. I have no problems
with adding the methods but when i feed this new node to tsort() I get
something like this

undefined method `size' for nil:NilClass
H:/ruby/somCompiler.rb:112:in `tsort_each_child'
c:/ruby/lib/ruby/1.8/tsort.rb:204:in
`each_strongly_connected_component_from
c:/ruby/lib/ruby/1.8/tsort.rb:183:in
`each_strongly_connected_component'
c:/ruby/lib/ruby/1.8/rexml/element.rb:939:in `each'
c:/ruby/lib/ruby/1.8/rexml/xpath.rb:53:in `each'
c:/ruby/lib/ruby/1.8/rexml/element.rb:939:in `each'
H:/ruby/somCompiler.rb:109:in `tsort_each_node'
......
From what I understand i am unable to add @dependencies array to the
REXML::Element.Is it not possible
or i am missing something terribly here?
Any help would be greatly appreciated..
Hurcan
 
G

Gary Wright

Although I am a seasoned C/C++ programmer(+10 years), I am relatively
new to the ruby (about 2 days) despite having some reservations(ruby
debugger should be theslowest thing in the world) i am otherwise very
impressed with the language, I intend to use Ruby for some code
generation task ,Everything was going well until i hit that roadblock

class REXML::Element
include TSort
def initialize
@dependencies=[]
end
def tsort_each_node(&block)
@elements.each(&block)
end
def tsort_each_child(node, &block)
@dependencies.each(&block) if @dependencies.size>0
end
end

Just a guess but I suspect your problem is that you've effectively
thrown away the initialize method for REXML::Element and replaced it
with your own. I think you want:

alias __original_initialize initialize
def initialize(*args, &block)
__original_initialize(*args, &block)
@dependencies = []
end

This way you make sure the original version of initialize
executes as well as your new code.

Gary Wright
 
R

Robert Klemme

Although I am a seasoned C/C++ programmer(+10 years), I am relatively
new to the ruby (about 2 days) despite having some reservations(ruby
debugger should be theslowest thing in the world) i am otherwise very
impressed with the language, I intend to use Ruby for some code
generation task ,Everything was going well until i hit that roadblock

class REXML::Element
include TSort
def initialize
@dependencies=[]
end
def tsort_each_node(&block)
@elements.each(&block)
end
def tsort_each_child(node, &block)
@dependencies.each(&block) if @dependencies.size>0
end
end

Just a guess but I suspect your problem is that you've effectively
thrown away the initialize method for REXML::Element and replaced it
with your own. I think you want:

alias __original_initialize initialize
def initialize(*args, &block)
__original_initialize(*args, &block)
@dependencies = []
end

This way you make sure the original version of initialize
executes as well as your new code.

While this is true, at least @dependencies should be properly
initialized unless REXML::Element instances are not created via new.

There's another gotcha: by including TSort initialization might be
broken, if TSort defines initialize and does not propagate to the parent
class.

To OP: "if @dependencies.size>0" can be rewritten as "unless
@dependencies.empty?" which again is superfluous here: #each will take
care of empty collections.

Maybe you need provide more code. From what you have shown so far it is
not clear to me why @dependencies would be nil.

Kind regards

robert
 
H

hurcan solter

Although I am a seasoned C/C++ programmer(+10 years), I am relatively
new to the ruby (about 2 days) despite having some reservations(ruby
debugger should be theslowest thing in the world) i am otherwise very
impressed with the language, I intend to use Ruby for some code
generation task ,Everything was going well until i hit that roadblock
class REXML::Element
include TSort
def initialize
@dependencies=[]
end
def tsort_each_node(&block)
@elements.each(&block)
end
def tsort_each_child(node, &block)
@dependencies.each(&block) if @dependencies.size>0
end
end

Just a guess but I suspect your problem is that you've effectively
thrown away the initialize method for REXML::Element and replaced it
with your own. I think you want:

alias __original_initialize initialize
def initialize(*args, &block)
__original_initialize(*args, &block)
@dependencies = []
end

This way you make sure the original version of initialize
executes as well as your new code.

Gary Wright

On the contrary, it's the original version that executes not mine.
You see,it's the REXML module that creates the Element instance
and it calls the original constructor(if it's the term) not mine. I
erronously thought
i am effectively replacing the REXML:Element with my own version.
What i am trying to accomplish is adding to an existing class a new
instance variable
in its definition.

For example
require "rexml/document"
include REXML

class REXML::Element
def some_method
puts "some_method called"
end

doc = Document.new File.open("mydoc.xml")
doc.each_element("somexmltag"){|node| # i have no intervention here
REXML does all the stuff
puts node.methods #=> ["some_method" "namespaces" "attributes"]
etc etc
node.some_method #=> some_method called
the above code snippet works, and adds a method to an existing class
in some other module
i just wonder is it possible to add some instance variable in same
manner?
 
G

Gary Wright

It looks like REXML already provides the two
iterators you need to satisfy TSort. Try this:

require 'rexml/document'
require 'tsort'

class REXML::Element
include TSort
def tsort_each_node(&block)
each_recursive(&block)
end
def tsort_each_child(node, &block)
node.each_child(&block) if node.respond_to?:)each_child)
end
end

doc = REXML::Document.new <<EOS
<mydoc>
<someelement attribute="nanoo">Text, text, text</someelement>
</mydoc>
EOS
p doc.tsort



Gary Wright
 
H

hurcan solter

It looks like REXML already provides the two
iterators you need to satisfy TSort. Try this:

require 'rexml/document'
require 'tsort'

class REXML::Element
include TSort
def tsort_each_node(&block)
each_recursive(&block)
end
def tsort_each_child(node, &block)
node.each_child(&block) if node.respond_to?:)each_child)
end
end

doc = REXML::Document.new <<EOS
<mydoc>
<someelement attribute="nanoo">Text, text, text</someelement>
</mydoc>
EOS
p doc.tsort

Gary Wright

well my sorting criteria something different from that.Consider this;

<fixedRecordData name="EntityIdentifierStruct">
<field name="orientation" dataType="OrientationStruct"/>
</fixedRecordData>
<fixedRecordData name="FederateIdentifierStruct">
<field name="SiteID" dataType="short int"/>
<field name="ApplicationID" dataType="long int"/>
</fixedRecordData>
EntityIdentifierStruct depends on FederateIdentifierStruct
and FederateIdentifierStruct depends on none (primitives not
important)
and i also have to extract that denpendency information from child
node attributes so one to one comparison wont work. So I have
to compose a dependency graph first and keep it somewhere
(I am thinking the element itself ,so the need for instance
variable) only
then i can give it to tsort_each_child to iterate over..,
hurcan
 
G

Gary Wright

well my sorting criteria something different from that.Consider this;

Then you are going to have to implement Tsort over a different type
of collection. Tsort uses the eql? method to compare nodes and I
don't think you want to mess around with REXML's notion of equality.

I think it would be better off iterating over all the nodes in the
document and creating a new dependency graph based on your criteria
and then applying Tsort to that new data structure instead of the
REXML data structure.

I'll admit to not looking too deep into your problem but I get the
feeling that you are applying TSort to the wrong data structure.

Gary Wright
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,732
Latest member
ArronPalin

Latest Threads

Top