Creating a method given a block

From: Hal E. Fulton [mailto:hal9000@hypermetrics.com]

Suppose I have a method ‘build’ to which I am passing
(among other things) a Symbol and a block.

The build method will define a method of the given
name and the block will in effect be the “body”
of that block.

I’ve been messing with Procs trying to get this to
work. Just can’t figure it out.

Here’s my quick take (without your extra args):

···


class Extendable
@@dispatch_table = Hash.new
def build(name, &block)
@@dispatch_table[name] = block
Extendable.class_eval <<-EVAL
def #{name.to_s}(*args)
@@dispatch_table[:#{name}].call(*args)
end
EVAL
end
end

a = Extendable.new
a.build(:foo) { |str| puts “foo:#{str}” }
a.build(:noo) { |str1, str2| puts “noo:#{str1};#{str2}” }

a.foo(“bar”) #-> “foo:bar”
a.noo(“baz”, “blah”) #-> “noo:baz;blah”

If you’re ‘eval’-averse, you could replace the class_eval with a
method_missing trap instead.

  • jeff

If you're 'eval'-averse, you could replace the class_eval with a

yes,

method_missing trap instead.

no :slight_smile:

pigeon% cat b.rb
#!/usr/bin/ruby
class Extendable
   def build(name, &block)
      class << self; self; end.send(:define_method, name, &block)
   end
end

a = Extendable.new
a.build(:foo) { |str| puts "foo:#{str}" }
a.build(:noo) { |str1, str2| puts "noo:#{str1};#{str2}" }

a.foo("bar") #-> "foo:bar"
a.noo("baz", "blah") #-> "noo:baz;blah"

b = Extendable.new
b.foo("aa")
pigeon%
pigeon% b.rb
foo:bar
noo:baz;blah
./b.rb:16: undefined method `foo' for #<Extendable:0x401afe4c> (NameError)
pigeon%

Guy Decoux