Morton Goldberg
10/25/2006 7:25:00 PM
I have a situation where I want to send many messages, one after the
other, to single object. Instead of writing, say,
foo.eat burger, fries
foo.drink beer
foo.be_merry
I want to be able to write something like:
foo.perform { eat burger, fries; drink beer; be_merry }
I'm not much at meta-programming. The best I've been able to come up
with so far is:
<code>
#! /usr/bin/env ruby -w
class Foo
def report
defined_here = (methods - Object.methods).join(", ")
puts "#{self.class.name} defines: " + defined_here
end
def say(text)
puts %[#{inspect} says "#{text}"]
end
def eat(*food)
food = food.join(" and ")
say "Downing #{food}. Yum, yum, yum!"
end
def drink(beverage)
say "Chug, chug, chug"
end
def be_merry
say "What, me worry?"
end
end
module Kernel
def tell(obj, to_do)
obj.instance_eval(to_do)
end
end
tell Foo.new, <<TO_DO
report
eat 'burger', 'fries'
drink 'beer'
be_merry
TO_DO
</code>
Although this works, it offends my sense of programming esthetics.
I'd rather pass in a block. Is there a way to do that? Something like:
<pseud-code>
module Kernel
def tell(obj, &to_do)
# what goes here?
end
end
tell Foo.new do
report
eat 'burger', 'fries'
drink 'beer'
be_merry
end
</pseud-code>
Instead of a Kernel#tell method, a Foo#perform method would be OK:
<pseud-code>
Foo.new.perform { report; eat 'burger', 'fries'; drink 'beer';
be_merry }
</pseud-code>
Regards, Morton