dynamic calling question

M

Martin Pirker

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
 
R

Robert Klemme

Martin Pirker said:
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
 
V

Vincent Isambart

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
 
M

Martin Pirker

Robert Klemme said:
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
 
R

Robert Klemme

Martin Pirker said:
Robert Klemme said:
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?> "func2" => lambda { method :whatever } }
=> {"func1"=># said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,252
Latest member
MeredithPl

Latest Threads

Top