From: Robert Klemme Date: 2008-01-19T00:38:35+09:00 Subject: Re: passing method references in python & ruby 2008/1/18, Justin Collins : > 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