[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Learning ruby - metaprogramming question [from poignant guide]

Luc Juggery

10/23/2006 11:19:00 AM

Hello all,

I started learning Ruby not long ago and I'd really like to understand
concepts behind it.
Poignant Guide to ruby (http://poignantguide.net/ruby/chap...)
is a very usefull book for this.
Below example is extracted from this book and some things remain quite
magical for me.

----------------------------------------------------------------------
# The guts of life force within Dwemthy's Array
class Creature

# Get a metaclass for this class
def self.metaclass; class << self; self; end; end

# Advanced metaprogramming code for nice, clean traits
def self.traits( *arr )
return @traits if arr.empty?

# 1. Set up accessors for each variable
attr_accessor *arr

# 2. Add a new class method to for each trait.
arr.each do |a|
metaclass.instance_eval do
define_method( a ) do |val|
@traits ||= {}
@traits[a] = val
end
end
end

# 3. For each monster, the `initialize' method
# should use the default number for each trait.
class_eval do
define_method( :initialize ) do
self.class.traits.each do |k,v|
instance_variable_set("@#{k}", v)
end
end
end

end


---------------------
class Creature
traits :life, :strength, :charisma, :weapon
end
---------------------


--------- generated Creature class ----------
class Creature

# 1. set up reader and writer methods
attr_accessor :life, :strength, :charisma, :weapon

# 2. add new class methods to use in creature
def self.life( val )
@traits ||= {}
@traits['life'] = val
end

def self.strength( val )
@traits ||= {}
@traits['strength'] = val
end

def self.charisma( val )
@traits ||= {}
@traits['charisma'] = val
end

def self.weapon( val )
@traits ||= {}
@traits['weapon'] = val
end

# 3. initialize sets the default points for
# each trait
def initialize
self.class.traits.each do |k,v|
instance_variable_set("@#{k}", v)
end
end

end
----------------------------------

The thing I do not really understand is the instance_eval and
class_eval in the self.traits method.
It seems that metaclass.instance_eval define_method create a Class
method in the Creature class. Creating a method in the singleton class
of a Class class always define a Class method? can the Singleton class
can also be used to create an instance method of Creature ? Is the way
presented in this example is what is commonly done to dynamically
define Class and instance method of a Class or are there any other
possible syntaxes ?

The self.traits method also define accessors methods: attr_accessor
*arr, how come this is not done within a define_method statement?

Well.... I hope I am not getting to confusing....
I would really appreciate your help as I'd really like to understand
how that's working.
I have already read several article on metaprogramming but some things
remain quite obscure to me :-)

Thanks a lot,
Luc

5 Answers

dblack

10/23/2006 11:31:00 AM

0

Luc Juggery

10/23/2006 11:36:00 AM

0

Thanks a lot David,
that clarified a lot of things in my head :-)

Luc

On 10/23/06, dblack@wobblini.net <dblack@wobblini.net> wrote:
> Hi --
>
> On Mon, 23 Oct 2006, Luc Juggery wrote:
>
> > The thing I do not really understand is the instance_eval and
> > class_eval in the self.traits method.
> > It seems that metaclass.instance_eval define_method create a Class
> > method in the Creature class. Creating a method in the singleton class
> > of a Class class always define a Class method?
>
> Yes.
>
> > can the Singleton class can also be used to create an instance
> > method of Creature ?
>
> No, those methods will not be visible to instances of Creature. Think
> of it from the object's perspective. Every object has a method
> look-up path, consisting of classes (including its singleton class)
> and modules. The whole point of a singleton class is that it lies on
> the look-up path of only one object. (There's one exception to this;
> see below.) Therefore, if the class object Creature has a method in
> its singleton class, and you do: c = Creature.new, c is a different
> object from Creature, and the methods defined in Creature's singleton
> class are not visible to it.
>
> The exception is subclasses. If you subclass Creature, the new class
> will be able to call Creature's singleton methods. It's a special
> arrangement so that class methods can be inherited.
>
> > Is the way presented in this example is what is commonly done to
> > dynamically define Class and instance method of a Class or are there
> > any other possible syntaxes ?
>
> You can use eval("def #{method_name}...") but it's fragile and
> inadvisable.
>
> > The self.traits method also define accessors methods: attr_accessor
> > *arr, how come this is not done within a define_method statement?
>
> The attr_* family of methods are basically wrappers around method
> definitions. They're just shorter and more convenient, but the effect
> is the same.
>
>
> David
>
> --
> David A. Black | dblack@wobblini.net
> Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
> DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
> [1] http://www.manning... | [3] http://www.rubypoweran...
> [2] http://dablog.r... | [4] http://www.rubyc...
>
>

Luc Juggery

10/23/2006 3:04:00 PM

0

Hi David,

Do you know where I could find some interesting doc on this, something
like "Ruby Metaprogramming for "REAL" dummy" :-) ?

Thanks a lot,

Luc

On 10/23/06, dblack@wobblini.net <dblack@wobblini.net> wrote:
> Hi --
>
> On Mon, 23 Oct 2006, Luc Juggery wrote:
>
> > The thing I do not really understand is the instance_eval and
> > class_eval in the self.traits method.
> > It seems that metaclass.instance_eval define_method create a Class
> > method in the Creature class. Creating a method in the singleton class
> > of a Class class always define a Class method?
>
> Yes.
>
> > can the Singleton class can also be used to create an instance
> > method of Creature ?
>
> No, those methods will not be visible to instances of Creature. Think
> of it from the object's perspective. Every object has a method
> look-up path, consisting of classes (including its singleton class)
> and modules. The whole point of a singleton class is that it lies on
> the look-up path of only one object. (There's one exception to this;
> see below.) Therefore, if the class object Creature has a method in
> its singleton class, and you do: c = Creature.new, c is a different
> object from Creature, and the methods defined in Creature's singleton
> class are not visible to it.
>
> The exception is subclasses. If you subclass Creature, the new class
> will be able to call Creature's singleton methods. It's a special
> arrangement so that class methods can be inherited.
>
> > Is the way presented in this example is what is commonly done to
> > dynamically define Class and instance method of a Class or are there
> > any other possible syntaxes ?
>
> You can use eval("def #{method_name}...") but it's fragile and
> inadvisable.
>
> > The self.traits method also define accessors methods: attr_accessor
> > *arr, how come this is not done within a define_method statement?
>
> The attr_* family of methods are basically wrappers around method
> definitions. They're just shorter and more convenient, but the effect
> is the same.
>
>
> David
>
> --
> David A. Black | dblack@wobblini.net
> Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
> DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
> [1] http://www.manning... | [3] http://www.rubypoweran...
> [2] http://dablog.r... | [4] http://www.rubyc...
>
>


--
@bientot,
Luc

Brian Neal

10/24/2006 3:17:00 AM

0

Luc Juggery wrote:
> Hi David,
>
> Do you know where I could find some interesting doc on this, something
> like "Ruby Metaprogramming for "REAL" dummy" :-) ?
>
> Thanks a lot,
>
> Luc

Hi Luc,

I have found Chapter 13, Ruby Dynamics, in Ruby for Rails by David A.
Black, to be a great resource for getting your head around
metaprogramming. I got started with Hal Fulton's The Ruby Way, which I
recommend as well (the 2nd edition comes out shortly, I think).

cheers,

Brian

--
Posted via http://www.ruby-....

Luc Juggery

10/24/2006 11:15:00 AM

0

Thanks a lot Brian,
I'll check this !!!!!

Luc

On 10/24/06, Brian Neal <rbneal@alltel.net> wrote:
> Luc Juggery wrote:
> > Hi David,
> >
> > Do you know where I could find some interesting doc on this, something
> > like "Ruby Metaprogramming for "REAL" dummy" :-) ?
> >
> > Thanks a lot,
> >
> > Luc
>
> Hi Luc,
>
> I have found Chapter 13, Ruby Dynamics, in Ruby for Rails by David A.
> Black, to be a great resource for getting your head around
> metaprogramming. I got started with Hal Fulton's The Ruby Way, which I
> recommend as well (the 2nd edition comes out shortly, I think).
>
> cheers,
>
> Brian
>
> --
> Posted via http://www.ruby-....
>
>