ruby metaprogramming I

just played a little with some basic groundwork of ruby’s potentials upon metaprogramming. metaprogramming still is and even will become more important in regard to the increasing relevance due to domain specific languages (dsl). in the context of modeling such a dsl and expressing domain specific concepts within it, metaprogramming is a powerful and very flexible option, since it will provide the full power of ruby’s features when it comes to modeling domain concepts.

with the rise of java 6 and especially the support for scripting languages (jsr 223 – scripting for the java platform) such potentials could become strategic, since half typed languages like java are quite inflexible for extensions due to domain specific needs. scripting languages like ruby could play an important role in the next future, since it will be very easy to interoperate. given this, one could take the power of both sides java and ruby, when it comes to the implementation of applications. one could apply the right instrument to the approriate parts of an application in order to benefit from the strength of each particular language. for example, web application layer could be done using rails, but java provides its full power under the hood when asking for security, transactionional services, distribution or integration of legacy systems. the core business logic (especially where the domain drives complexity) could be expressed using a domain specific language, again falling back to ruby’s above mentioned potentials …

so much for the motivation … now to the action …

come in – we’re open, too

one basic feature of ruby’s possibilities due to metaprogramming is its facility of extending almost everything, even ‘build in’ classes. so its very easy to enrich a given class with new features.

if we would ask a number if it’s an odd one, we would receive a reaction like the following:

 > 23.odd? 
NoMethodError: undefined method `odd?' for 23:Fixnum

this is normal behaviour since class Fixnum doesn’t provide such a method.
but thanks to the openness of classes, we can enhance Fixnum at any time and pay for a new method:

class Fixnum 
    def odd? 
        self % 2 == 1 
    end 
end

if we now ask the number a second time, the sun will shine again …

> 23.odd?
=> true

enhancing class features

what about enhancing the features of class itself?
you may know about ‘attr_reader’ or ‘attr_writer’ in order to define instance properties without explicitly defining ‘getters’ and ‘setters’ (sorry, i’m originally a java guy).

class Person     
    attr_reader :firstname, :lastname, :birthday     
    attr_writer :firstname, :lastname, :birthday   
end

we have to do so – declaring attr_reader for offering ‘getter’ and declaring attr_writer for offering ‘setter’ functionality – because there’s no feature of declaring both ‘setter’ and ‘getter’ in one go.
now, if we would consider it nice to have such a feature – let’s enhance …

since everything is an object in Ruby world, also Class is nothing more than a specific class that – among others – inherits from Object, you can of course also enhance the definition of class and let all class definitions (which ‘uses’ Class) benefit from that enhancements:

class Class      
    def attr_rw( *attrib_names )       
        attrib_names.each do |name|         
            attr_reader name 
            attr_writer name 
        end 
    end 
end

as you can see, Class now owns a new method attr_rw, which delegates the passed property names to both attr_reader and attr_writer, means that both ‘getter’ and ‘setter’ functionality will be assigned.

we now could use this new feature as it would be a normal ‘keyword’ of the language, like attr_reader or attr_writer:

class Person        
    attr_rw :firstname, :lastname, :birthday 
end

admitted, this is a very simple example, but it shows the power of enhancing the ‘core’ language with new ‘concepts’ quite well.
it’s a first step towards the way of metaprogramming …

Advertisements
Posted in ruby. 7 Comments »

7 Responses to “ruby metaprogramming I”

  1. Mariano Kamp Says:

    Hi,

    very nice.

    >>we have to do so – declaring attr_reader for offering ‘getter’ and declaring attr_writer for offering ‘setter’ functionality – because there’s no feature of declaring both ‘setter’ and ‘getter’ in one go.
    now, if we would consider it nice to have such a feature – let’s enhance …

    It’s kind of beside the point of your posting, but you are aware that attr_rw is already part of Ruby? It is called attr_accessor and works as advertised.

    Still, it’s always good to read about Metaprogramming.

    Cheers,
    Mariano, also from Frankfurt… You should come to http://frankfurtonrails.de/public/article?article_id=1

  2. Mario Gleichmann Says:

    hi Mariano,

    thanks for your helpfull hint. in fact, i didn’t know about ‘attr_accessor’. since i would consider myself as a very newbie to Ruby, there are doubtless a whole stack of features i don’t know about …

    … still playin’ and learning … :o)

    greetings

    Mario

    p.s. thank you also for your link to the user group. as soon as i’ll have the time, i would in fact like to come to one of your public meetings.

  3. Mariano Kamp Says:

    Yeah, sure.

    It is still nice to see that you could extend the language the way you described. That says something about the power of Ruby.

    Mariano

  4. David Says:

    “because there’s no feature of declaring both ‘setter’ and ‘getter’ in one go.”

    What about attr_accessor? Isn’t that for defining getter and setter method in one go?

  5. Mario Gleichmann Says:

    hi David,

    you are absolutely right. this is exactly the functionality of attr_accessor!
    since i am unfortenately restricted by time (‘allowed to’ work with java over day ;o)) i havn’t got a good survey of all ruby features …
    hope the blog gives nevertheless a first little insight to the motivations of metaprogramming.

  6. Mike Joyce Says:

    Don’t forget that there’s ‘attr’ where you give it a bool as to whether you want it writable or not.

    attr :rw1, true
    attr :rw2, true
    attr :ro1
    attr :ro2, false

  7. Mario Gleichmann Says:

    hi Mike,

    thanks for your advice. another feature i didn’t know about …

    as i said before – still playin’ around and learning almost every day a new ‘cool’ ruby feature … ;o)


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: