13

So, I want to define a singleton method for an object, but I want to do it using a closure.

For example,

def define_say(obj, msg)
  def obj.say
    puts msg
  end
end

o = Object.new
define_say o, "hello world!"
o.say

This doesn't work because defining a singleton method via "def" is not a closure, so I get an exception that "msg" is an undefined variable or method.

What I would like to do is something like using the "define_method" method in the Module class, but as far as I can tell, this can only be used to define a method on a class... but I want a Singleton Method...

So, I would love to write it something like this:

def define_say(obj, msg)
  obj.define_singleton_method(:say) {
    puts msg
  }
end

Does anyone know how I can achieve this without having to create a method to store a Proc and then use the Proc within a singleton method? (basically, I want a clean, non-hacky way of doing this)

2 Answers 2

15

Object#define_singleton_method was added to ruby-1.9.2 by the way:

def define_say(obj, msg)
  obj.define_singleton_method(:say) do
    puts msg
  end
end
Sign up to request clarification or add additional context in comments.

Comments

8

Here's an answer which does what you're looking for

def define_say(obj, msg)
  # Get a handle to the singleton class of obj
  metaclass = class << obj; self; end 

  # add the method using define_method instead of def x.say so we can use a closure
  metaclass.send :define_method, :say do
    puts msg
  end
end

Usage (paste from IRB)

>> s = "my string"
=> "my string"
>> define_say(s, "I am S")
=> #<Proc:0xb6ed55b0@(irb):11>
>> s.say
I am S
=> nil

For more info (and a little library which makes it less messy) read this:

http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html

As an aside, If you're a ruby programmer, and you HAVEN'T read that, go do it now~!

1 Comment

I changed the link, because _why went AWOL since this answer was posted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.