Passing methods as parameters - the nice way?

Hello all,

I’m pretty new to ruby, but have some background in Java, and very
little
C(++) and suchlike.
I’m currently - as a “learning-by-doing”-project - creating a simple
text-based interface for running (more or less) arbitrary programs.
I decided on a simple tree-based structure for the menu itself, however
I’m
a bit stuck on the hook between my interface, and the program running
behind
it.

In order to not couple my interface too tightly to my program running
behind
it, I’d really like for my interface to not know what it’s actually
interfacing with.
Basically, I just figured I could take a leaf from the
Functional-programming style and give my TextInterface a method to call
when
I told it to:
def call_action
if(@action_method)
send(@action_method)
end
end

which works fine, as long as my method is defined “in the wild”:

def foo
puts “foo called”
end

interface.set_action(:foo)
interface.call_action => foo called

but, how do I handle it if the method is an instance method on some
object?
program = Program.new
interface.set_action(:program.foo)?
No variant of this works for me.

I realise I may be fundamentally wrong in my approach, so any tips would
be
welcome. :slight_smile:

Regards,

Søren Andersen

On Oct 24, 6:31 pm, “Søren Andersen” [email protected] wrote:

interface.set_action(:foo)
interface.call_action => foo called

but, how do I handle it if the method is an instance method on some object?
program = Program.new
interface.set_action(:program.foo)?
No variant of this works for me.

You should pass the target object to the interface as well, and then
do “my_obj.send(an_instance_method_foo)”

Doh, ofc.

I should have figured that out myself.

Thank you!

Regards,

Søren

Søren Andersen wrote:

Hello all,

I told it to:
def call_action
if(@action_method)
send(@action_method)
end
end

which works fine, as long as my method is defined “in the wild”:

def foo
puts “foo called”
end

interface.set_action(:foo)
interface.call_action => foo called

I’d suggest using blocks instead of the above construct. Your code
transformed:

def on_action(&block)
@action = block
end

def action
@action.call if @action
end

obj = Object.new
def obj.foo; puts “foo on #{self.inspect} called”; end

interface.on_action { obj.foo }
interface.action

alternatively:

interface.on_action(&obj.method(:foo))
interface.action

Blocks are far more flexible than passing a method name or instance.

Regards
Stefan

On 10/24/07, Stefan R. [email protected] wrote:

transformed:
def obj.foo; puts “foo on #{self.inspect} called”; end
Regards
Stefan

Thanks! I’ll try this approach as well!

Regards,

Søren