Method_added/define_method infinite loop

What’s the best way to avoid the classic method_added/define_method
infinite loop?

class X
def self.method_added(name)
p name
define_method(name)
# do something else
end
end

 def foo; end

end

This will, of course, print “foo” forever.

As an aside, anyone else think method_added should also receive a
block of the method definition? E.g. this would be a “push” (less the
infinite loop issue):

def self.method_added(name, &block)
  define_method(name, &block)
end

Thanks!
T.

On Nov 13, 2007, at 7:24 AM, Trans wrote:

  define_method(name, &block)
end

Thanks!
T.

cfp:~ > cat a.rb
class X
class << self
def ignoring_added_methods
ignoring_added_methods = @ignoring_added_methods
@ignoring_added_methods = true
yield
ensure
@ignoring_added_methods = ignoring_added_methods
end

 def ignoring_added_methods?
   defined? @ignoring_added_methods and @ignoring_added_methods
 end

 def method_added name
   return if ignoring_added_methods?
   ignoring_added_methods do
     p name
     define_method(:bar){}
   end
 end

end

def foo
end

end

cfp:~ > ruby a.rb
:foo

a @ http://codeforpeople.com/

On Nov 13, 3:36 pm, “ara.t.howard” [email protected] wrote:

  define_method(name)

block of the method definition? E.g. this would be a “push” (less the
class X
defined? @ignoring_added_methods and @ignoring_added_methods

def foo
end

end

cfp:~ > ruby a.rb
:foo

nice. i like the way you did that. thanks ara.

only question i have is about thread safety --could the instance var
pose a potential problem with that?

T.

On Nov 13, 2007 8:24 AM, Trans [email protected] wrote:

This will, of course, print “foo” forever.

As an aside, anyone else think method_added should also receive a
block of the method definition? E.g. this would be a “push” (less the
infinite loop issue):

def self.method_added(name, &block)
  define_method(name, &block)
end

I might be missing something, but I cannot think of a practical use
for that. It re-defined the method with the same name and
content…Why?

On Nov 13, 1:36 pm, “ara.t.howard” [email protected] wrote:

 def ignoring_added_methods?
   defined? @ignoring_added_methods and @ignoring_added_methods
 end

What was your motivation for the above code instead of simply
def ignoring_added_methods?
@ignoring_added_methods
end

On Nov 13, 2007, at 8:40 PM, Phrogz wrote:

cfp:~ > ruby -d -e ’ def foo() defined? @foo and @foo end; foo() ’

cfp:~ > ruby -d -e ’ def foo() @foo end; foo() ’
-e:1: warning: instance variable @foo not initialized

been trying to get the habit… it’s tough! :wink:

cheers.

a @ http://codeforpeople.com/

On Nov 13, 11:16 pm, “Chris C.” [email protected] wrote:

end

I might be missing something, but I cannot think of a practical use
for that. It re-defined the method with the same name and
content…Why?

I’m impractical ? :wink:

meta-programming. In this instance, I was working on a Traits idea. I
need to rename every method defined and keep track of it and replace
it with a method that weaves together these renamed methods.

T.

On Nov 13, 2007, at 8:12 PM, Trans wrote:

only question i have is about thread safety --could the instance var
pose a potential problem with that?

probably. maybe (untested):

cfp:~ > cat a.rb
class X
class << self
def ignoring_added_methods
ignoring_added_methods = @ignoring_added_methods
@ignoring_added_methods = true
yield
ensure
@ignoring_added_methods = ignoring_added_methods
end

  def ignoring_added_methods?
    defined? @ignoring_added_methods and @ignoring_added_methods
  end

  def method_added name
    Thread.critical = true
    return if ignoring_added_methods?
    ignoring_added_methods do
      p name
      define_method(:bar){}
    end
  ensure
    Thread.critical = false
  end
end

 def foo
 end

end

cheers.

a @ http://codeforpeople.com/