Mucking about with dynamically adding methods to objects

I’ve been toying with Ruby for a while, but only now am I beginning to
understand some of the amazing properties Ruby has. I was simply
floored when I realise you could add methods to an object dynamically.

So I saw this:

obj=Object.new

def obj.talk
puts “Hello!”
end

and was stunned. obj now has a talk method!

I took it to the next logical step, making a class which could add
methods to objects:

class FairyGodmother
def talkify(obj)
def obj.talk
puts “I’m a real boy!”
end
end
end

fairy = FairyGodother.new()
pinocchio = Object.new()

fairy.talkify(pinochio)

pinochio.talk # Success!

But my next logical leap doesn’t work:

Changing the talkify method to this:

def talkify(obj, str)
def obj.talk
puts str
end
end

doesn’t do what I mean - what it does is create a method called talk
which tries to output obj.str which doesn’t exist. What I want is for
the obj.talk method to return the literal string given to the
fairy.talkify call.

How do I convince Ruby to evaluate str?

(Apologies if this is answered somewhere in The Well Grounded Rubyist

[email protected]

On Thu, Sep 17, 2009 at 11:44 AM, Paul S. [email protected]
wrote:

doesn’t do what I mean - what it does is create a method called talk
which tries to output obj.str which doesn’t exist. What I want is for
the obj.talk method to return the literal string given to the
fairy.talkify call.

The problem here is that def starts a new scope, so str is undefined
there.
This is a try with define_object instead:

irb(main):012:0> class A
irb(main):013:1> def talkify(obj,str)
irb(main):014:2> (class << obj;self;end).instance_eval do
irb(main):015:3* define_method :talk do
irb(main):016:4* puts str
irb(main):017:4> end
irb(main):018:3> end
irb(main):019:2> end
irb(main):020:1> end
=> nil
irb(main):021:0> o = Object.new
=> #Object:0xb7d62cf4
irb(main):023:0> A.new.talkify o,“hi”
=> #Proc:[email protected]:15(irb)
irb(main):024:0> o.talk
hi
=> nil

We call define_method in the singleton class of obj. We need the
instance_eval because define_method is private.

Hope this helps,

Jesus.

2009/9/17 Jesús Gabriel y Galán [email protected]:

end
irb(main):013:1> def talkify(obj,str)
irb(main):023:0> A.new.talkify o,“hi”
=> #Proc:[email protected]:15(irb)
irb(main):024:0> o.talk
hi
=> nil

We call define_method in the singleton class of obj. We need the
instance_eval because define_method is private.

Hope this helps,

Thanks

I think I have a lot more reading to do before

irb(main):014:2> (class << obj;self;end).instance_eval do
irb(main):015:3* define_method :talk do

makes any kind of sense.

Paul S.
http://www.nomadicfun.co.uk

[email protected]

Hi –

On Fri, 18 Sep 2009, Paul S. wrote:

irb(main):014:2> (class << obj;self;end).instance_eval do
irb(main):015:3* define_method :talk do

Here’s a starting point: http://www.wobblini.net/singletons.html

David

On Thu, Sep 17, 2009 at 5:28 PM, Paul S. [email protected]
wrote:

2009/9/17 Jesús Gabriel y Galán [email protected]:

On Thu, Sep 17, 2009 at 11:44 AM, Paul S. [email protected] wrote:

I think I have a lot more reading to do before

irb(main):014:2> (class << obj;self;end).instance_eval do
irb(main):015:3* define_method :talk do

makes any kind of sense.

David’s article is a good starting point to understand singleton
classes and methods. Anyway,
(class << obj; self; end) is a very common idiom to access the
singleton class of an object.
Some people even do:

class Object
def singleton_class
class << self; self; end;
end
end

Maybe with this addition, what I wrote is a little bit more clear:

obj.singleton_class.instance_eval do
define_method :talk do
puts str
end
end

As we need to refer to str, we use define_method, which doesn’t define
a new scope, so str is available in the block passed to define_method,
which is a closure. In order to call define_method, which is private,
we need an environment in which self is the object that we wan’t to
call define_method on*. In our case this object is the singleton class
of “obj”. The method instance_eval does exactly that: evaluate the
block in a context in which self is set to the receiver of
instance_eval.

Hope this clarifies a little bit more.

  • Another way is to use send

obj.singleton_class.send(:define_method, :talk) do
puts str
end

but I like instance_eval better.

Jesus.

On Thursday 17 September 2009 10:28:25 am Paul S. wrote:

I think I have a lot more reading to do before

irb(main):014:2> (class << obj;self;end).instance_eval do
irb(main):015:3* define_method :talk do

makes any kind of sense.

Break it down into pieces. You already know how to do:

def obj.talk

end

Or, to define a class method:

Class Foo
def self.bar

end
end
Foo.bar

The next step is to realize that this is equivalent to:

class << obj
def talk

end
end

It might not be immediately obvious, but just take my word for it: that
is
equivalent to ‘def obj.talk’.

But it looks like a class definition – and it sort of is. It’s the
metaclass
– you can think of it as a class that only that object belongs to,
which
inherits from the object’s real, official class.

Now, think about this example:

class Foo
def self.bar

You might’ve already done it this way:

def Foo.bar

So what is self inside a class? Easy, it’s the class itself.

So, what’s self inside “class << object”? It’s the metaclass I just
described.

So, if you do this:

meta_class = class << object
self
end

you extract the metaclass. (The last statement in a class definition is
the
return value of the class definition.)

Once you understand that much, instance_eval may make sense. In fact,
you
could do this:

class Object
def metaclass
class << self; self; end
end
end

Now you can do object.metaclass.instance_eval. This is so incredibly
common
that it could be shortened, too:

class Object
def meta_eval &block
metaclass.instance_eval &block
end
end

I use this a lot – even when “class << obj” would work just as well.
And I’m
blatantly stealing this from _why – he distributed it as a gem called
‘metaid’. His Rubyforge account seems to work, and the gem seems to be
alive,
so I think it’s safe – especially since it’s so fundamental and obvious
(17
lines of code) that it’s not hard to replace if you have to.

So, do this instead:

gem install metaid

require ‘metaid’
def talkify(obj, str)
obj.meta_eval do
define_method :talk do
str
end
end
end

I might shorten it like this, if it fits well:

require ‘metaid’
def talkify obj, str
obj.metaclass.send :define_method, :talk do
str
end
end

It’s probably covered somewhere in that book, but even once it is, I
still
suggest metaid.

Paul S. wrote:

2009/9/17 Jes�s Gabriel y Gal�n [email protected]:

end
irb(main):013:1> def talkify(obj,str)
irb(main):023:0> A.new.talkify o,“hi”
=> #Proc:[email protected]:15(irb)
irb(main):024:0> o.talk
hi
=> nil

We call define_method in the singleton class of obj. We need the
instance_eval because define_method is private.

Hope this helps,

Thanks

I think I have a lot more reading to do before

irb(main):014:2> (class << obj;self;end).instance_eval do
irb(main):015:3* define_method :talk do

makes any kind of sense.

This isn’t going to work:

def talkify(obj, str)
def obj.talk
puts str
end
end

because in ruby nested methods do not form “closures”. That means a
nested method cannot see the local variables(including the parameter
variables) in the enclosing method.

However, blocks can see variables in the surrounding scope, for example:

def meth
x = 10
arr = [1, 2, 3]

arr.each{|num| puts num + x}
end

–output:–
11
12
13

So that suggests a strategy for devising a solution to your problem:
try to employ a block to capture the variables in the surrounding scope
instead of a method definition.

This is what I came up with:

class FairyGodmother

def get_singleton_class(obj)

class << obj
  self
end

end

end

  1. Inside a class definition, like:

class << obj
self
end

and outside any method definitions, self is the class object, which in
this case is the singleton class of obj.

  1. A class definition actually returns the last statement evaluated
    inside the class, for instance:

return_val = class A
10
end

p return_val

–output:–
10

  1. A method returns the value of the last statement evaluated in the
    method.

The method get_singleton_class(obj) returns the singelton class of obj
because this:

def get_singleton_class(obj)

class << obj
  self
end

end

becomes this:

def get_singleton_class(obj)

obj_singleton

end

which returns obj_singleton. (See p. 392 in your book if that’s not
clear.)

Then you can define talkify() like this:

class FairyGodmother

def talkify(obj, str)
obj_singleton = get_singleton_class(obj)
p = Proc.new {puts str}
obj_singleton.send(:define_method, “talk”, p)
end

end

fairy = FairyGodmother.new()
pinochio = Object.new()

fairy.talkify(pinochio, “hello”)
pinochio.talk

–output:–
hello

On Thu, Sep 17, 2009 at 7:17 PM, 7stud – [email protected]
wrote:

7stud – wrote:

Thank you very much for all your careful explanations - Ruby is making
a lot more sense to me as the days go by :slight_smile:

To put it in context, I learned C++ some 7 years ago or so, and was
blown away by how OO changed what I’d learnt wih Basic and Assembler
up to that point. I thought I knew about OO until I hit Ruby about 2
years ago, but didn’t seriously look into the language. This time
around, things are making even more sense to me in Ruby, and I’m
enjoying the ride - I’m even using Ruby in the Google Code Jam this
year just for the fun of it.

It’s been said before, but Ruby programming really is fun.


Paul S.
http://www.nomadicfun.co.uk

[email protected]

Paul S. wrote:

I think I have a lot more reading to do before

irb(main):014:2> (class << obj;self;end).instance_eval do
irb(main):015:3* define_method :talk do

makes any kind of sense.

I just started chapter 14 of the “The Well Grounded Rubyist”, and
instance_eval() and define_method() are explained in regards to a
similar example.

Something that bothered me when I initially read that code was the use
of instance_eval(). I was left wondering why the more natural-reading
class_eval() wasn’t used? After all, the goal is to create a method in
the singleton class.

You can do this with class_eval():

class FairyGodmother

def get_singleton_class(obj)

class << obj
  self
end
#explained on p.392

end

def talkify(obj, str)
obj_singleton = get_singleton_class(obj)

obj_singleton.class_eval %Q{

  def talk
    puts "hello"
  end

}

end
end

…but if you try this:

def talkify(obj, str)
obj_singleton = get_singleton_class(obj)

obj_singleton.class_eval %Q{

  def talk
    puts str    #<---CHANGE HERE****
  end

}

end

…it doesn’t work. The def creates a new scope, and str is not defined
inside the def.

Using a string as an argument for class_eval() is unwieldy. Luckily,
class_eval() will take a block–instead of a string:

def talkify(obj, str)
obj_singleton = get_singleton_class(obj)

obj_singleton.class_eval do

  def talk
    puts 'hello'
  end

end

But once again, the def creates a new scope, so the code inside the def
can’t reference variables outside the def–like str(which is one of
talkify()'s parameter variables).

define_method() to the rescue:

def talkify(obj, str)
obj_singleton = get_singleton_class(obj)

obj_singleton.class_eval do

  define_method("talk") do
    puts str
  end

end

Neither of the blocks used with class_eva() or define_method() creates a
new scope, so code inside them can make use of variables defined in the
surrounding scope.

Anyway, after working through that example, I wonder if there is a
difference between instance_eval() and class_eval() when the receiver is
a class?

7stud – wrote:

However, blocks can see variables in the surrounding scope, for example:

def meth
x = 10
arr = [1, 2, 3]

arr.each{|num| puts num + x}
end

–output:–
11
12
13

I guess a more pertinent example would be:

def meth(val)
arr = [1, 2, 3]

arr.each{|num| puts num + val}
end

meth(10)

–output:–
11
12
13

7stud – wrote:

define_method() to the rescue:

def talkify(obj, str)
obj_singleton = get_singleton_class(obj)

obj_singleton.class_eval do

  define_method("talk") do
    puts str
  end

end

Neither of the blocks used with class_eva() or define_method() creates a
new scope, so code inside them can make use of variables defined in the
surrounding scope.

Hmm…I’ve decided that I find that explanation totally unsatisfying.
If define_method() really created a method, then inside the created
method str would be undefined. Since str isn’t undefined when the talk
‘method’ is called, define_method() must really create a closure
somewhere along the line, i.e. something like a Proc object. Maybe
define_method() creates a method that calls a Proc object? For
instance, something like this:

def talk
a_proc.call
end

where a_proc is created like this:

a_proc = Proc.new {puts str}

which forms a closure, so all the variables in scope at the time a_proc
was created can be referenced inside a_proc.

7stud – wrote:

…but if you try this:

def talkify(obj, str)
obj_singleton = get_singleton_class(obj)

obj_singleton.class_eval %Q{

  def talk
    puts str    #<---CHANGE HERE****
  end

}

end

…it doesn’t work. The def creates a new scope, and str is not defined
inside the def.

To be clearer, that should read:

…it doesn’t work. When the string is evaluated inside the singleton
class, the def creates a new scope, and the str variable is not defined
inside the def.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs