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 …
November 23, 2007 at 9:35 pm
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
November 23, 2007 at 9:37 pm
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.
November 23, 2007 at 9:37 pm
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
November 23, 2007 at 9:38 pm
“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?
November 23, 2007 at 9:38 pm
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.
November 23, 2007 at 9:40 pm
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
November 23, 2007 at 9:40 pm
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)