From: Sean Middleditch Date: 2001-08-08T07:15:59+09:00 Subject: [ruby-talk:19312] Re: Virtual list On 08 Aug 2001 05:59:50 +0900, Niklas Frykholm wrote: > > For starts, I'm new to Ruby still, forgive me naivette. (Is that even a > > word?) I'm mostly a C++ programmer, so my terminology might be a little off > > towards that direction.. ^,^ > > > > If I have a class Object (in C++, called AMObject in Ruby), and it has two > > lists in it - a list of attributes (properties of an item), and containers > > (difference types of containers that store more Objects), how can I make a > > clean interface to traversing these objects in Ruby? > > > > In C++ the tree is like: > > Object (class object) > > attributes (class list) > > obj_attr > > obj_attr > > ... > > containers (class list) > > container > > container > > ... > > > > Something like this in Ruby would be nice: > > obj.attrs.for_each { |a| whatever... } > > How do I go about making a clean class for "attrs?" > > I am not entirely sure I understand you, but to me it seems as if you are > still thinking in "static typing". Remember that Ruby is dynamically typed, > each object knows its own type, so you don't need to specify it. > Got that part. ^,^ > So to create a list of objects you would just put them in a Ruby array, > no matter what their type was. > > attr = [attr1, attr2, attr3, ...] > > And then you could indeed do attr.each {..} or use any of the other methods > for ruby arrays. > Ah, see, the issue is that the Ruby objects won't exist to put into an array. I need kind of a "virtual" array that will create the Ruby objects on the fly from the C++ objects in the C++ list, when the Ruby array is accessed. Also, when a new Ruby object is placed into the array, the C++ class needs to be pulled out (check the Ruby class of the object, of course) which would mean something like obj.attrs.add (AMAttribute.new ("type", "data", "etc")) would create an instance of the C++ class obj_attr (wrapped in the class AMAttribute in Ruby), and pass that to the attrs object, which would basically take the obj_attr pointer from the AMAttribute instance, and call the following C++ code: obj->attrs.add (obj_attr_instance); The each member function of the attrs class (in Ruby) would call C++ code that would loop thru all the elements in the C++ list, construct the Ruby wrapper for the class, and call the yield'ed function on them. I was wondering how I could easily create a class like this that not only works for any object on the Ruby side, but also is clean and functional on the C++ side (where static typing and type checking are very important). > As for the containers, put them in an array as well, and let each of the > containers define "each" and include Enumerable. Then you can use all the > containers in the same way. (But you may not even need different containers, > since Array can hold objects of any type, it is good for most things.) > > If you are used to static typing you may very well think that this seems > "unclean", but as you get more used to dynamic typing you will worry > less and less about that. > > // Niklas > Sean Etc.