Dynamic calling question

On implementing a state machine I'm stuck at...

h = Hash::new
h["func1"] = "Outer::Inner::dothis"
h["func2"] = "whatever"

def whatever(x)
puts "whatever happens #{x}"
end

module Outer
  module Inner
    def dothis(c)
      puts "I did it #{c} times"
    end
    module_function :dothis
  end
end

Outer::Inner::dothis(3)
__send__(h["func2"],9)
__send__(h["func1"],7)

=== cut here ===

$ ruby ztrick.rb

I did it 3 times
whatever happens 9
ztrick.rb:21:in '__send__': undefined method 'Outer::Inner::dothis' for main:Object (NoMethodError)
        from ztest.rb:21

local calls look ok - how to do dynamic calls across module/class boundaries?
consider the hash mostly populated first and the functions are defined later
(or never at all)
I'm not even sure whether this is a syntax or missunderstanding issue :-/

any hints on how to do a fast state machine appreciated

thanks!
Martin

"Martin Pirker" <crf@sbox.tu-graz.ac.at> schrieb im Newsbeitrag
news:41176b8e$0$18044$3b214f66@aconews.univie.ac.at...

On implementing a state machine I'm stuck at...

h = Hash::new
h["func1"] = "Outer::Inner::dothis"
h["func2"] = "whatever"

def whatever(x)
puts "whatever happens #{x}"
end

module Outer
  module Inner
    def dothis(c)
      puts "I did it #{c} times"
    end
    module_function :dothis
  end
end

Outer::Inner::dothis(3)
__send__(h["func2"],9)
__send__(h["func1"],7)

=== cut here ===

$ ruby ztrick.rb

I did it 3 times
whatever happens 9
ztrick.rb:21:in '__send__': undefined method 'Outer::Inner::dothis' for

main:Object (NoMethodError)

        from ztest.rb:21

local calls look ok - how to do dynamic calls across module/class

boundaries?

consider the hash mostly populated first and the functions are defined

later

(or never at all)
I'm not even sure whether this is a syntax or missunderstanding issue

:-/

Misunderstanding I guess: __send__ without an instance sends to self,
which in this case != Outer::Inner. So for the general case you need also
need the instance that the message should be sent to. Try this:

h = Hash::new
h["func1"] = Outer::Inner.method :dothis
h["func2"] = method :whatever

def whatever(x)
puts "whatever happens #{x}"
end

module Outer
  module Inner
    def dothis(c)
      puts "I did it #{c} times"
    end
    module_function :dothis
  end
end

Outer::Inner::dothis(3)
h["func2"].call 9
h["func1"].call 7

Regards

    robert

ztrick.rb:21:in '__send__': undefined method 'Outer::Inner::dothis' for main:Object (NoMethodError)
        from ztest.rb:21

It does not work because send will only call a method of the object you call it on. Outer::Inter::dothis is not a method name, but the name of a module with a method name at the end.
But there is a way for it to work, just replace your __send__ with a call to my little smart_call:
def smart_call(name, *params)
   array = name.split(/::/)
   # array[0...-1] contains the modules list
   # array[-1] contains the class name
   array[0...-1].inject(Kernel) { |memo, obj| memo.const_get(obj) }.send(array[-1], *params)
end
I'm sure it could be written in a better way, but I am not a pro in Ruby ^o^
It just gets the wanted module (using const_get) and calls the method on it.

Regards,
Vincent Isambart

Try this:

h["func1"] = Outer::Inner.method :dothis
h["func2"] = method :whatever

[defs]

Outer::Inner::dothis(3)
h["func2"].call 9
h["func1"].call 7

appears to work with .call instead of __send__, but this requires def first
otherwise one can't get the .method (of course...)

  ztrick.rb:5: uninitialized constant Outer (NameError)

I'll try do guarantee that the def is always first... hmmm

Martin

···

Robert Klemme <bob.news@gmx.net> wrote:

"Martin Pirker" <crf@sbox.tu-graz.ac.at> schrieb im Newsbeitrag
news:41179c87$0$18702$3b214f66@aconews.univie.ac.at...

> Try this:

> h["func1"] = Outer::Inner.method :dothis
> h["func2"] = method :whatever

[defs]

> Outer::Inner::dothis(3)
> h["func2"].call 9
> h["func1"].call 7

appears to work with .call instead of __send__, but this requires def

first

otherwise one can't get the .method (of course...)

  ztrick.rb:5: uninitialized constant Outer (NameError)

I'll try do guarantee that the def is always first... hmmm

Well, that's the standard approach, isn't it? Of course if you want it lazy
you can use blocks to defer execution of #method like this:

$ irbs

h={ "func1" => lambda { Outer::Inner.method :dothis },

?> "func2" => lambda { method :whatever } }
=> {"func1"=>#<Proc:0x10183188@(irb):1>,
"func2"=>#<Proc:0x10183020@(irb):2>}

def whatever(x) puts "Whatever #{x}" end

=> nil

h["func2"].call.call "you want"

Whatever you want
=> nil

Btw, what problem are you trying to solve?

Kind regards

    robert

···

Robert Klemme <bob.news@gmx.net> wrote: