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
- I haven't finished the book yet :slight_smile: )

···

--
Paul Smith
http://www.nomadicfun.co.uk

paul@pollyandpaul.co.uk

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@(irb):15>
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.

···

On Thu, Sep 17, 2009 at 11:44 AM, Paul Smith <paul@pollyandpaul.co.uk> wrote:

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.

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.

···

2009/9/17 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>:

On Thu, Sep 17, 2009 at 11:44 AM, Paul Smith <paul@pollyandpaul.co.uk> wrote:

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.

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@(irb):15>
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,

--
Paul Smith
http://www.nomadicfun.co.uk

paul@pollyandpaul.co.uk

Hi --

···

On Fri, 18 Sep 2009, Paul Smith 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

--
David A. Black, Director
Ruby Power and Light, LLC (http://www.rubypal.com)
Ruby/Rails training, consulting, mentoring, code review
Book: The Well-Grounded Rubyist (http://www.manning.com/black2\)

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 Thu, Sep 17, 2009 at 5:28 PM, Paul Smith <paul@pollyandpaul.co.uk> wrote:

2009/9/17 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>:

On Thu, Sep 17, 2009 at 11:44 AM, Paul Smith <paul@pollyandpaul.co.uk> 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.

···

On Thursday 17 September 2009 10:28:25 am Paul Smith 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.

Paul Smith wrote:

end

irb(main):013:1> def talkify(obj,str)
irb(main):023:0> A.new.talkify o,"hi"
=> #<Proc:0xb7d64f40@(irb):15>
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.

2) 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

3) 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

···

2009/9/17 Jes�s Gabriel y Gal�n <jgabrielygalan@gmail.com>:

--
Posted via http://www.ruby-forum.com/\.

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

···

--
Posted via http://www.ruby-forum.com/\.

<snip>

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.

···

On Thu, Sep 17, 2009 at 7:17 PM, 7stud -- <bbxx789_05ss@yahoo.com> wrote:

7stud -- wrote:

--
Paul Smith
http://www.nomadicfun.co.uk

paul@pollyandpaul.co.uk

Paul Smith 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?

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

--
Posted via http://www.ruby-forum.com/\.