20070525

Pointers About References

I believe I mentioned before about really wishing I had pointers in Ruby. In the implementation of each class that's able to be loaded from XML data, there are several "properties" that describe each piece of data that would be described within its XML node. The main XML loading function (called loadProperties(), actually) knows how to take input XML data and a property object (not the original class, but a property object in the class) and load the data. So the property object needs to have pointers to the original class, in order to set the actual data values in there.

Since Ruby doesn't exactly have a pointer or reference type built in, I instead passed in two Procs: a getter and a setter. Due to the nature of closures, these allowed me to reference a member method of the correct object. At the same time, you had to manually create these stupid cookie-cutter procs for each property. Down the line, when there may be 100 properties in an XML readable class, that's a lot of extra, stupid code. There had to be a better way.

Turns out someone already wrote a pretty good Reference library for Ruby that does exactly what I want. It's a "gem," so I had to go install the whole RubyGems thing, but that's fine. The reference library, in its easiest use, takes symbols and turns them into references. Here's how it cut down the code I had before.

"Before" code.

"After" code:

@props << PersistedProperty.new(
              'short_description',
              ref(:shortDescription),
              String,
              protoRef(:shortDescription))

As you can see in the bolded portion, all I have to do is pass in the name of the accessor method in my current object, and it takes care of creating the "reference" for me. The magic behind the scenes for why calling this special ref method works is that ref is mixed in to Object. I'll leave the rest of that train of thought as an exercise to the reader.

The protoRef method creates a similar kind of reference, except to a property of this object's prototype (only applicable in classes that are prototyped, of course). I wrote that one myself. In any case, it cuts down my code significantly. I feel a lot better about the conciseness of this code.

lach:~/prog/ruby/mud/trunk$ svn log -r HEAD
------------------------------------------------------------------------
r151 | k | 2007-05-25 09:23:30 -0400 (Fri, 25 May 2007) | 6 lines

- give a more concise way of passing the procs in to PersistedProperty
- using Reference class
- use ref(:sym) to point to the method sym() in the current class
- use protoRef(:sym) to point to proto().sym()
- pass PersistedProperty.UseNewTypeFallback for procGetFallback to use prop.type.new() as the fallback
------------------------------------------------------------------------

0 comments:

Post a Comment