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:0xb7d64f40@: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:0xb7d64f40@: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:0xb7d64f40@: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.