[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Dynamic Methods not Behaving as Expected

Marc Merlin

12/21/2004 12:46:00 AM

Motivation: I would like to create an "imposter" class that supports the
definition of dynamically-defined methods. Once defined, these dynamic
methods should be invokable as though they were garden-variety
statically-defined methods.

Problem: The dynamic methods implemented in the following code (and other
work-arounds I've tried) don't seem to exhibit the exact same behavior as
their static counterparts. In particular, blocks attached at the point of
method invocation don't seem to be detected.

Execution Context: ruby 1.8.2 (2004-11-06) [i686-linux]

Question: What am I missing?

Code: <<-EOS

class Imposter
def solicit(request)
self.class.send(:define_method, request, &Proc.new)
end

def dull_method
puts "dull_method called: block_given?=#{block_given?}"
end
end

imposter = Imposter.new

imposter.solicit(:dyno_method) do
puts "dyno_method called: block_given?=#{block_given?}"
end

imposter.dull_method
imposter.dull_method { nil }

imposter.dyno_method
imposter.dyno_method { nil }

EOS

Output:
dull_method called: block_given?=false
dull_method called: block_given?=true
dyno_method called: block_given?=false
dyno_method called: block_given?=false

Any explanations would be appreciated!
Thanks,
Marc

1 Answer

Florian Gross

12/21/2004 1:35:00 AM

0

Marc Merlin wrote:

> Motivation: I would like to create an "imposter" class that supports the
> definition of dynamically-defined methods. Once defined, these dynamic
> methods should be invokable as though they were garden-variety
> statically-defined methods.
>
> Problem: The dynamic methods implemented in the following code (and other
> work-arounds I've tried) don't seem to exhibit the exact same behavior as
> their static counterparts. In particular, blocks attached at the point of
> method invocation don't seem to be detected.

Unfortunately .define_method can not be used to define methods with
blocks before Ruby 1.9 because blocks have no block slots.

You can workaround that by doing this:

create_wrapper = lambda do |name|
instance_eval %{
def #{name}(*args, &block)
#{name}_block(block, *args)
end
%}
end

define_method(:foo_block) { |block, *args| puts "foo!" }
create_wrapper.call(:foo)

It's not the most beautiful thing of the world but at least it can be
abstracted away easily...