Robert Klemme
1/18/2008 3:39:00 PM
2008/1/18, Justin Collins <justincollins@ucla.edu>:
> rpardee@gmail.com wrote:
> > Hey all,
> >
> > Kind of an idle, syntax comparison question here...
> >
> > In python, you can apparently pass method references around very
> > easily. So imagine you have these 2 functions defined:
> >
> > def firstWay(arg1, arg2)
> > return 'Tastes great.'
> >
> > def secondWay(arg1, arg2)
> > return 'Less filling.'
> >
> > Then you can define a method that takes a method name as an argument,
> > and calls it just by throwing parens (and any expected arguments of
> > course) after it.
> >
> > def doStuff(whichway, first_arg, second_arg)
> > return whichway(first_arg, second_arg)
> >
> > So calling:
> >
> > puts doStuff(firstWay, None, None)
> >
> > Would result in 'Tastes great.'
> >
> > What's the most graceful way to do this sort of thing in ruby? I
> > tried passing in e.g., firstWay.to_proc, but that got me a complaint
> > about not having enough arguments on the call. I can imagine doing,
> > e.g.,
> >
> > first_pointer = Proc.new do |foo, bar|
> > return firstWay(foo, bar)
> > end
> >
> > One for each alternate method & passing one of those in. I can also
> > imagine having doStuff take a block that would call the desired
> > function & yielding out to that. But neither of those are as pretty
> > as the python I think. Are those my best options in ruby, or is there
> > another way?
> >
> > Thanks!
> >
> > -Roy
> >
> >
>
> Here is another way:
>
> irb(main):001:0> def dostuff(whichway, arg1, arg2)
> irb(main):002:1> send(whichway, arg1, arg2)
> irb(main):003:1> end
> => nil
#dostuff is really superfluous because the way you defined it it's
just an alias for #send.
> irb(main):004:0> def first_way(arg1, arg2)
> irb(main):005:1> "tastes great"
> irb(main):006:1> end
> => nil
> irb(main):007:0> def second_way(arg1, arg2)
> irb(main):008:1> "less filling"
> irb(main):009:1> end
> => nil
> irb(main):010:0> dostuff(:first_way, nil, nil)
> => "tastes great"
> irb(main):011:0> dostuff(:second_way, nil, nil)
> => "less filling"
> irb(main):012:0> "No! #{dostuff(:first_way, nil, nil).capitalize}!"
> => "No! Tastes great!"
So basically you would just do
send(:first_way, nil, nil)
send(:second_way, nil, nil)
However, if there are /many/ alternatives, then - depending on
circumstances - a Hash might be a better alternative:
algorithms = {
:first_way => lambda {|a,b| 'Tastes great.'},
:second_way => lambda {|a,b| 'Less filling'},
# more algorithms here...
}
# ...
puts algorithms[:first_way][nil, nil]
puts algorithms[:second_way][nil, nil]
Kind regards
robert
--
use.inject do |as, often| as.you_can - without end