Dispatching when function name is stated as a symbol

Can someone point out an elegant way to solve the following problem?

I have a module with a function f and additional functions g1, g2, …,
which basically looks like this:

module M
def f(&cb)

x=cb.call
# DO SOMETHING … see below
end
def g1(a,b,c)

end
def g2(d,e)

end

etc

end

The DO SOMETHING part looks like this: The proc object being called
is supposed to return an array, where the first element is a symbol
corresponding to one of the function names g1, g2 …, and the
remaining array elements corresponding to the parameters of this
function. Hence, if
x=cb.call
causes x to contain [:g2, 25, ‘dummy’], I would like to execute
g2(25,‘dummy’)

I have not found a convincing way of doing this. Of course I can
use a big case … end on the function names (ugly). I can turn
the symbol :g2 into a string ‘g2’, marshal the arguments and put
together a string containing the function call (even uglier).
I also thought about using a hash of proc object (the keys being
the symbols, the values being the procedures), kind of

{:g1 => proc {|a,b,c] g1(a,b,c)}, :g2 => proc {|d,e| g2(d,e)
},…}[x[0]].
call(*x[1…-1])

but this looks like tremendous overkill too. Is there a simpler
way of doing it?

Ronald

Ronald F. [email protected]
Phone: +49-89-452133-162

On 8/31/07, Ronald F. [email protected] wrote:

end
is supposed to return an array, where the first element is a symbol
corresponding to one of the function names g1, g2 …, and the
remaining array elements corresponding to the parameters of this
function. Hence, if
x=cb.call
causes x to contain [:g2, 25, ‘dummy’], I would like to execute
g2(25,‘dummy’)

I have not found a convincing way of doing this.

Would this work for you?

def f(&cb)
x=cb.call
name = x[0]
args = x[1…-1]
send(name, *args);
end

def g1(a,b,c)
puts “g1: #{a}, #{b}, #{c}”
end

def g2(d,e)
puts “g1: #{a}, #{b}, #{c}”
end

irb(main):017:0> f {[:g1, 1, 2, 3]}
g1: 1, 2, 3
=> nil
irb(main):018:0> f {[:g2, 1, 2, 3]}
g2: 1, 2, 3
=> nil

Hope this helps,

Jesus.

On 8/31/07, Jesús Gabriel y Galán [email protected] wrote:

On 8/31/07, Ronald F. [email protected] wrote:

    puts "g1: #{a}, #{b}, #{c}"

end

def g2(d,e)
puts “g1: #{a}, #{b}, #{c}”

Oooops, typo. That should of course read:

puts “g2: #{a}, #{b}, #{c}”

x=cb.call
name = x[0]
args = x[1…-1]
send(name, *args);
end

Thank you! Works like a charm!

Ronald

On Aug 31, 2007, at 4:48 AM, Ronald F. wrote:

x=cb.call
Ronald F. [email protected]
Phone: +49-89-452133-162

Why bother to split the name out of the array? Just do:

send(*x)

If you really wanted to separate the name from the rest of the args,
it might be more efficient (guessing, not benchmarked!) to say:

name = x.shift
send(name, *x)

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

On Aug 31, 2007, at 4:48 AM, Ronald F. wrote:

x=cb.call
name = x[0]
args = x[1…-1]
send(name, *args);
end

It can made even simpler:

def f(&cb)
send(*cb.call)
end

def g1(a,b,c)
puts “g1: #{a}, #{b}, #{c}”
end

def g2(d,e)
puts “g2: #{d}, #{e}”
end

f { [:g1, 1, 2, 3] } # >> g1: 1, 2, 3
f { [:g2, 2, 3] } # >> g2: 2, 3

Regards, Morton

send(*x)

Simply because in my application, (1) the name gets prepended
a prefix before sending it, and (2) a few other arguments
are also put in the parameter list before sending. I didn’t
mention these details, because I thought at the time of writing
that they would only overly complicate the description of my
case.

If you really wanted to separate the name from the rest of the args,
it might be more efficient (guessing, not benchmarked!) to say:

name = x.shift
send(name, *x)

Thank you for this suggestion.

Ronald